]> sjero.net Git - dccp2tcp/blobdiff - dccp2tcp.c
Connection closing improvements and explicit cleanup code
[dccp2tcp] / dccp2tcp.c
index 12f6c451191affbe809ac06d6c06060a4a996879..dbd90dfc39832683cacbefdefdd7202add5f7f63 100644 (file)
@@ -1,19 +1,18 @@
 /******************************************************************************
 Author: Samuel Jero
 
-Date: 2/2011
+Date: 7/2011
 
 Description: Program to convert a DCCP flow to a TCP flow for DCCP analysis via
                tcptrace.
 
 Notes:
-       1)Supports only a single DCCP contection per capture
-       2)Source Port!=Destination Port
-       3)DCCP MUST use 48 bit sequence numbers
-       4)Checksums are not computed (they are zeroed)
-       5)Only implements those packet types normally used in a session
-       6)DCCP Ack packets show up as TCP packets containing one byte
-       7)Very little error checking of packet headers
+       1)CCID2 ONLY
+       2)DCCP MUST use 48 bit sequence numbers
+       3)Checksums are not computed (they are zeroed)
+       4)Only implements those packet types normally used in a session
+       5)DCCP Ack packets show up as TCP packets containing one byte
+       6)Very little error checking of packet headers
 ******************************************************************************/
 #include "dccp2tcp.h"
 
@@ -23,23 +22,22 @@ 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 seq_num *s1;    /*sequence number structure for side one of connection*/
-struct seq_num *s2;    /*sequence number structure for side two of connection*/
+pcap_t*                        in;                     /*libpcap input file discriptor*/
+pcap_dumper_t  *out;           /*libpcap output file discriptor*/
+struct connection *chead;      /*connection list*/
 
 
 
 void PcapSavePacket(struct pcap_pkthdr *h, u_char *data);
 void process_packets();
 void handle_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes);
-void convert_packet(struct pcap_pkthdr *h, const u_char *odata, u_char *ndata);
+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 seq_num **seq, __be16 source, __be32 initial);
-u_int32_t add_new_seq(struct seq_num *seq, __be32 num, int size, enum dccp_pkt_type type);
-u_int32_t convert_ack(struct seq_num *seq, __be32 num);
-int acked_packet_size(struct seq_num *seq, __be32 num);
-void ack_vect2sack(struct seq_num *seq, struct tcphdr *tcph, u_char* tcpopts, u_char* dccphdr, __be32 dccpack);
+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);
 
 
 /*Parse commandline options and open files*/
@@ -80,7 +78,7 @@ int main(int argc, char *argv[])
                                green=1;
                        }
                        if(argv[i][1]=='s' && strlen(argv[i])==2){ /*sack option*/
-                               sack=1;
+                               sack++;
                        }
                }
        }
@@ -126,12 +124,16 @@ int main(int argc, char *argv[])
        }
 
        /*process packets*/
+       chead=NULL;
        u_char *user=(u_char*)out;
        pcap_loop(in, -1, handle_packet, user); 
        
        /*close files*/
        pcap_close(in);
        pcap_dump_close(out);
+
+       /*Delete all connections*/
+       cleanup_connections();
 return 0;
 }
 
@@ -139,24 +141,40 @@ return 0;
 /*call back function for pcap_loop--do basic packet handling*/
 void handle_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
 {
-       u_char *ndata;
-       struct pcap_pkthdr nh;
+       u_char                          *ndata;
+       struct pcap_pkthdr      nh;
+       int                                     link_type;
+       struct packet           new;
+       struct const_packet     old;
+
+       /*Determine the link type for this packet*/
+       link_type=pcap_datalink(in);
 
        /*create new libpcap header*/
        memcpy(&nh, h, sizeof(struct pcap_pkthdr));
 
+       /*Setup packet structs*/
+       old.h=h;
+       old.length=h->caplen;
+       old.data=bytes;
+       new.h=&nh;
+       new.length=MAX_PACKET;
+
        /*create buffer for new packet*/
-       ndata=malloc(MAX_PACKET);
+       new.data=ndata=malloc(MAX_PACKET);
        if(ndata==NULL){
                dbgprintf(0,"Error: Couldn't allocate Memory\n");
                exit(1);
        }
 
        /*make sure the packet is all zero*/
-       memset(ndata, 0, MAX_PACKET);   
+       memset(new.data, 0, MAX_PACKET);
        
        /*do all the fancy conversions*/
-       convert_packet(&nh, bytes, ndata);
+       if(!do_encap(link_type, &new, &old)){
+               free(ndata);
+               return;
+       }
 
        /*save packet*/
        pcap_dump(user,&nh, ndata);
@@ -167,46 +185,65 @@ return;
 
 
 /*do all the dccp to tcp conversions*/
-void convert_packet(struct pcap_pkthdr *h, const u_char *odata, u_char *ndata)
+int convert_packet(struct packet *new, const struct const_packet* old)
 {      
-       u_char* ncur=ndata;
-       const u_char* ocur=odata;
-       int length=h->caplen;
-       struct iphdr *iph;
-       struct tcphdr *tcph;
-       struct dccp_hdr *dccph;
-       struct dccp_hdr_ext *dccphex;
-       struct dccp_hdr_ack_bits *dccphack;
-       int datalength;
-       const u_char* pd;
-       u_char* npd;
-       u_char* tcpopt;
-
-       /*copy ethernet and ip headers over*/
-       memcpy(ncur, ocur, sizeof(struct ether_header)+sizeof(struct iphdr) );
-       ocur+=sizeof(struct ether_header)+ sizeof(struct iphdr);
-       ncur+=sizeof(struct ether_header) +sizeof(struct iphdr);
-       length-=sizeof(struct ether_header) +sizeof(struct iphdr);
-
-       /*set ip to indicate that tcp is next protocol*/
-       iph= (struct iphdr *) (ncur - sizeof(struct iphdr));
-       iph->protocol=6;
-       iph->check=htonl(0);
+       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;
+
+       /*Safety checks*/
+       if(!new || !old || !new->data || !old->data || !new->h || !old->h){
+               dbgprintf(0,"Error:  Convert Packet Function given bad data!\n");
+               exit(1);
+               return 0;
+       }
+       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;
+       }
 
        /*cast header pointers*/
-       tcph=(struct tcphdr*)ncur;
-       tcpopt=ncur+ sizeof(struct tcphdr);
-       dccph=(struct dccp_hdr*)ocur;
-       dccphex=(struct dccp_hdr_ext*)(ocur+sizeof(struct dccp_hdr));
-       dccphack=(struct dccp_hdr_ack_bits*)(ocur+ sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
+       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)));
 
+       /*Get Hosts*/
+       if(get_host(new->src_id, new->dest_id, dccph->dccph_sport, dccph->dccph_dport, &h1, &h2)){
+               dbgprintf(0,"Error: Can't Get Hosts!\n");
+               return 0;
+       }
+       if(h1==NULL || h2==NULL){
+               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");
+               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=ntohs(iph->tot_len) - sizeof(struct iphdr) - dccph->dccph_doff*4;
-       pd=odata + sizeof(struct ether_header)+sizeof(struct iphdr) + dccph->dccph_doff*4;
+       datalength=old->length - dccph->dccph_doff*4;
+       pd=old->data + dccph->dccph_doff*4;
 
-       /*set tcp standard features*/
+       /*set TCP standard features*/
        tcph->source=dccph->dccph_sport;
        tcph->dest=dccph->dccph_dport;
        tcph->doff=5;
@@ -221,58 +258,55 @@ void convert_packet(struct pcap_pkthdr *h, const u_char *odata, u_char *ndata)
        /*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);
+                       }
+                       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;
 
-               if(yellow){
-                       tcph->window=htons(0);
-               }
-               tcph->ack_seq=htonl(0);
-               tcph->seq=htonl(initialize_seq(&s1, dccph->dccph_sport, 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++;
+                       }
 
-               /* add Sack-permitted option, if relevant*/
-               if(sack){
-                       *tcpopt=4;
-                       tcpopt++;
-                       *tcpopt=2;
-                       tcph->doff++;
+                       /*calculate length*/
+                       len=tcph->doff*4;
                }
-
-               /*set libpcap header lengths*/
-               h->len=sizeof(struct ether_header) + sizeof(struct iphdr) + tcph->doff*4;
-               h->caplen=sizeof(struct ether_header) + sizeof(struct iphdr) + tcph->doff*4;
-
-               /*set length in ip header*/
-               iph->tot_len=htons(sizeof(struct iphdr) + tcph->doff*4);
        }
 
        if(dccph->dccph_type==DCCP_PKT_RESPONSE){//DCCP RESPONSE-->TCP SYN,ACK
                dbgprintf(2,"Packet Type: Response\n");
-               tcph->ack_seq=htonl(convert_ack(s1,ntohl(dccphack->dccph_ack_nr_low)));
-               if(yellow){
-                       tcph->window=htons(0);
-               }
-               tcph->seq=htonl(initialize_seq(&s2, dccph->dccph_sport, 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=4;
-                       *(tcpopt+1)=2;
-                       tcph->doff++;
-               }
+               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;
 
-               /*set libpcap header lengths*/
-               h->len=sizeof(struct ether_header) + sizeof(struct iphdr) + tcph->doff*4;
-               h->caplen=sizeof(struct ether_header) + sizeof(struct iphdr) + tcph->doff*4;
+                       /* add Sack-permitted option, if relevant*/
+                       if(sack){
+                               tcpopt=(u_char*)(new->data + tcph->doff*4);
+                               *tcpopt=4;
+                               *(tcpopt+1)=2;
+                               tcph->doff++;
+                       }
 
-               /*set length in ip header*/
-               iph->tot_len=htons(sizeof(struct iphdr) + tcph->doff*4);
+                       /*calculate length*/
+                       len=tcph->doff*4;
+               }
        }
 
        if(dccph->dccph_type==DCCP_PKT_DATA){//DCCP DATA----Never seen in packet capture
@@ -282,31 +316,18 @@ void convert_packet(struct pcap_pkthdr *h, const u_char *odata, u_char *ndata)
 
        if(dccph->dccph_type==DCCP_PKT_DATAACK){//DCCP DATAACK-->TCP ACK with data
                dbgprintf(2,"Packet Type: DataAck\n");
-               if(s1 && dccph->dccph_sport==s1->addr){ //determine which side of connection is sending this packet
-                       if(green){
-                               tcph->ack_seq=htonl(convert_ack(s2,ntohl(dccphack->dccph_ack_nr_low)));
-                       }else{
-                               tcph->ack_seq=htonl(convert_ack(s2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
-                       }
-                       tcph->seq=htonl(add_new_seq(s1, ntohl(dccphex->dccph_seq_low),datalength, dccph->dccph_type));
-                       if(yellow){
-                               tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(s2, ntohl(dccphack->dccph_ack_nr_low)));
-                       }
-                       if(sack){
-                               ack_vect2sack(s2, tcph, tcpopt, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
-                       }
+               if(green){
+                       tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
                }else{
-                       if(green){
-                               tcph->ack_seq=htonl(convert_ack(s1,ntohl(dccphack->dccph_ack_nr_low)));
-                       }else{
-                               tcph->ack_seq=htonl(convert_ack(s1,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
-                       }
-                       tcph->seq=htonl(add_new_seq(s2, ntohl(dccphex->dccph_seq_low),datalength,dccph->dccph_type));
-                       if(yellow){
-                               tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(s1, ntohl(dccphack->dccph_ack_nr_low)));
-                       }
-                       if(sack){
-                               ack_vect2sack(s2, tcph, tcpopt, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
+                       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),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) );
                        }
                }
 
@@ -316,50 +337,30 @@ void convert_packet(struct pcap_pkthdr *h, const u_char *odata, u_char *ndata)
                tcph->rst=0;
 
                /*copy data*/
-               npd=ndata+ sizeof(struct ether_header)+sizeof(struct iphdr)+ tcph->doff*4;
+               npd=new->data + tcph->doff*4;
                memcpy(npd, pd, datalength);
 
-               /*set libpcap header lengths*/
-               h->len=sizeof(struct ether_header) + sizeof(struct iphdr) + tcph->doff*4 + datalength;
-               h->caplen=sizeof(struct ether_header) + sizeof(struct iphdr) + tcph->doff*4 + datalength;
-
-               /*set length in ip header*/
-               iph->tot_len=htons(sizeof(struct iphdr) + tcph->doff*4 + datalength);
+               /*calculate length*/
+               len= tcph->doff*4 + datalength;
        }
 
        if(dccph->dccph_type==DCCP_PKT_ACK){ //DCCP ACK -->TCP ACK with no data
                dbgprintf(2,"Packet Type: Ack\n");
-               if(s1 && dccph->dccph_sport==s1->addr){//determine which side of connection is sending this packet
-                       if(green){
-                               tcph->ack_seq=htonl(convert_ack(s2,ntohl(dccphack->dccph_ack_nr_low)));
-                       }else{
-                               tcph->ack_seq=htonl(convert_ack(s2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
-                       }
-                       tcph->seq=htonl(add_new_seq(s1, 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)h->ts.tv_sec, (int)h->ts.tv_usec);
-                               }
-                       }
-                       if(sack){
-                               ack_vect2sack(s2, tcph, tcpopt, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
-                       }
+               if(green){
+                       tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
                }else{
-                       if(green){
-                               tcph->ack_seq=htonl(convert_ack(s1,ntohl(dccphack->dccph_ack_nr_low)));
-                       }else{
-                               tcph->ack_seq=htonl(convert_ack(s1,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
-                       }
-                       tcph->seq=htonl(add_new_seq(s2, 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)h->ts.tv_sec, (int)h->ts.tv_usec);
-                               }
+                       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){
-                               ack_vect2sack(s1, tcph, tcpopt, (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) );
                        }
                }
 
@@ -368,12 +369,8 @@ void convert_packet(struct pcap_pkthdr *h, const u_char *odata, u_char *ndata)
                tcph->fin=0;
                tcph->rst=0;
 
-               /*set libpcap header lengths*/
-               h->len=sizeof(struct ether_header) + sizeof(struct iphdr) + tcph->doff*4 + 1;
-               h->caplen=sizeof(struct ether_header) + sizeof(struct iphdr) + tcph->doff*4 + 1;
-
-               /*set length in ip header*/
-               iph->tot_len=htons(sizeof(struct iphdr) + tcph->doff*4 + 1);
+               /*calculate length*/
+               len=tcph->doff*4 + 1;
        }
 
        if(dccph->dccph_type==DCCP_PKT_CLOSEREQ){//DCCP CLOSEREQ----Never seen in packet capture
@@ -383,31 +380,19 @@ void convert_packet(struct pcap_pkthdr *h, const u_char *odata, u_char *ndata)
 
        if(dccph->dccph_type==DCCP_PKT_CLOSE){//DCCP CLOSE-->TCP FIN,ACK
                dbgprintf(2,"Packet Type: Close\n");
-               if(s1 && dccph->dccph_sport==s1->addr){//determine which side of connection is sending this packet
-                       if(green){
-                               tcph->ack_seq=htonl(convert_ack(s2,ntohl(dccphack->dccph_ack_nr_low)));
-                       }else{
-                               tcph->ack_seq=htonl(convert_ack(s2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
-                       }
-                       tcph->seq=htonl(add_new_seq(s1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
-                       if(yellow){
-                               tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(s2, ntohl(dccphack->dccph_ack_nr_low)));
-                       }
-                       if(sack){
-                               ack_vect2sack(s2, tcph, tcpopt, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
-                       }
+               update_state(h1,CLOSE);
+               if(green){
+                       tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
                }else{
-                       if(green){
-                               tcph->ack_seq=htonl(convert_ack(s1,ntohl(dccphack->dccph_ack_nr_low)));
-                       }else{
-                               tcph->ack_seq=htonl(convert_ack(s1,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
-                       }
-                       tcph->seq=htonl(add_new_seq(s2, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
-                       if(yellow){
-                               tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(s1, ntohl(dccphack->dccph_ack_nr_low)));
-                       }
-                       if(sack){
-                               ack_vect2sack(s1, tcph, tcpopt, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
+                       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) );
                        }
                }
 
@@ -416,41 +401,27 @@ void convert_packet(struct pcap_pkthdr *h, const u_char *odata, u_char *ndata)
                tcph->fin=1;
                tcph->rst=0;
 
-               /*set libpcap header lengths*/
-               h->len=sizeof(struct ether_header) + sizeof(struct iphdr) + tcph->doff*4;
-               h->caplen=sizeof(struct ether_header) + sizeof(struct iphdr) + tcph->doff*4;
-
-               /*set length in ip header*/
-               iph->tot_len=htons(sizeof(struct iphdr) + tcph->doff*4);
+               /*calculate length*/
+               len=tcph->doff*4;
        }
 
        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(s1 && dccph->dccph_sport==s1->addr){//determine which side of connection is sending this packet
-                       if(green){
-                               tcph->ack_seq=htonl(convert_ack(s2,ntohl(dccphack->dccph_ack_nr_low)));
-                       }else{
-                               tcph->ack_seq=htonl(convert_ack(s2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
-                       }
-                       tcph->seq=htonl(add_new_seq(s1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
-                       if(yellow){
-                               tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(s2, ntohl(dccphack->dccph_ack_nr_low)));
-                       }
-                       if(sack){
-                               ack_vect2sack(s2, tcph, tcpopt, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
-                       }
+               if(green){
+                       tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
                }else{
-                       if(green){
-                               tcph->ack_seq=htonl(convert_ack(s1,ntohl(dccphack->dccph_ack_nr_low)));
-                       }else{
-                               tcph->ack_seq=htonl(convert_ack(s1,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
-                       }
-                       tcph->seq=htonl(add_new_seq(s2, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
-                       if(yellow){
-                               tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(s1, ntohl(dccphack->dccph_ack_nr_low)));
-                       }
-                       if(sack){
-                               ack_vect2sack(s1, tcph, tcpopt, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
+                       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) );
                        }
                }
 
@@ -459,45 +430,26 @@ void convert_packet(struct pcap_pkthdr *h, const u_char *odata, u_char *ndata)
                tcph->fin=1;
                tcph->rst=0;
 
-               /*set libpcap header lengths*/
-               h->len=sizeof(struct ether_header) + sizeof(struct iphdr) + tcph->doff*4;
-               h->caplen=sizeof(struct ether_header) + sizeof(struct iphdr) + tcph->doff*4;
-
-               /*set length in ip header*/
-               iph->tot_len=htons(sizeof(struct iphdr) + tcph->doff*4);
+               /*calculate length*/
+               len=tcph->doff*4;
        }
 
        if(dccph->dccph_type==DCCP_PKT_SYNC){//DCCP SYNC
                dbgprintf(2,"Packet Type: Sync\n");
-               if(s1 && dccph->dccph_sport==s1->addr){//determine which side of connection is sending this packet
-                       if(green){
-                               tcph->ack_seq=htonl(convert_ack(s2,ntohl(dccphack->dccph_ack_nr_low)));
-                       }else{
-                               tcph->ack_seq=htonl(convert_ack(s2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
-                       }
-                       tcph->seq=htonl(add_new_seq(s1, ntohl(dccphex->dccph_seq_low),0,dccph->dccph_type));
-                       if(yellow){
-                               tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(s2, ntohl(dccphack->dccph_ack_nr_low)));
-                       }else{
-                               tcph->window=htons(0);
-                       }
-                       if(sack){
-                               ack_vect2sack(s2, tcph, tcpopt, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
-                       }
+               if(green){
+                       tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
                }else{
-                       if(green){
-                               tcph->ack_seq=htonl(convert_ack(s1,ntohl(dccphack->dccph_ack_nr_low)));
-                       }else{
-                               tcph->ack_seq=htonl(convert_ack(s1,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
-                       }
-                       tcph->seq=htonl(add_new_seq(s2, ntohl(dccphex->dccph_seq_low),0,dccph->dccph_type));
-                       if(yellow){
-                               tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(s1, ntohl(dccphack->dccph_ack_nr_low)));
-                       }else{
-                               tcph->window=htons(0);
-                       }
-                       if(sack){
-                               ack_vect2sack(s1, tcph, tcpopt, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
+                       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) );
                        }
                }
 
@@ -506,45 +458,26 @@ void convert_packet(struct pcap_pkthdr *h, const u_char *odata, u_char *ndata)
                tcph->fin=0;
                tcph->rst=0;
 
-               /*set libpcap header lengths*/
-               h->len=sizeof(struct ether_header) + sizeof(struct iphdr) + tcph->doff*4+ 0;
-               h->caplen=sizeof(struct ether_header) + sizeof(struct iphdr) + tcph->doff*4+ 0;
-
-               /*set length in ip header*/
-               iph->tot_len=htons(sizeof(struct iphdr) + tcph->doff*4+0);
+               /*calculate length*/
+               len=tcph->doff*4;
        }
 
        if(dccph->dccph_type==DCCP_PKT_SYNCACK){//DCCP SYNACK
                dbgprintf(2,"Packet Type: SyncAck\n");
-               if(s1 && dccph->dccph_sport==s1->addr){//determine which side of connection is sending this packet
-                       if(green){
-                               tcph->ack_seq=htonl(convert_ack(s2,ntohl(dccphack->dccph_ack_nr_low)));
-                       }else{
-                               tcph->ack_seq=htonl(convert_ack(s2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
-                       }
-                       tcph->seq=htonl(add_new_seq(s1, ntohl(dccphex->dccph_seq_low),0,dccph->dccph_type));
-                       if(yellow){
-                               tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(s2, ntohl(dccphack->dccph_ack_nr_low)));
-                       }else{
-                               tcph->window=htons(0);
-                       }
-                       if(sack){
-                               ack_vect2sack(s2, tcph, tcpopt, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low));
-                       }
+               if(green){
+                       tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
                }else{
-                       if(green){
-                               tcph->ack_seq=htonl(convert_ack(s1,ntohl(dccphack->dccph_ack_nr_low)));
-                       }else{
-                               tcph->ack_seq=htonl(convert_ack(s1,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
-                       }
-                       tcph->seq=htonl(add_new_seq(s2, ntohl(dccphex->dccph_seq_low),0,dccph->dccph_type));
-                       if(yellow){
-                               tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(s1, ntohl(dccphack->dccph_ack_nr_low)));
-                       }else{
-                               tcph->window=htons(0);
-                       }
-                       if(sack){
-                               ack_vect2sack(s1, tcph, tcpopt, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
+                       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));
                        }
                }
 
@@ -553,23 +486,22 @@ void convert_packet(struct pcap_pkthdr *h, const u_char *odata, u_char *ndata)
                tcph->fin=0;
                tcph->rst=0;
 
-               /*set libpcap header lengths*/
-               h->len=sizeof(struct ether_header) + sizeof(struct iphdr) + tcph->doff*4+0;
-               h->caplen=sizeof(struct ether_header) + sizeof(struct iphdr) + tcph->doff*4+0;
-
-               /*set length in ip header*/
-               iph->tot_len=htons(sizeof(struct iphdr) + tcph->doff*4+0);
+               /*calculate length*/
+               len=tcph->doff*4;
        }
 
        if(dccph->dccph_type==DCCP_PKT_INVALID){//DCCP INVALID----Never seen in packet capture
                dbgprintf(0,"Invalid DCCP Packet!!\n");
-               exit(1);
+               return 0;
        }
-return;
+
+       new->length=len;
+return 1;
 }
 
 
-/*Parse Ack Vector Options*/
+/*Parse Ack Vector Options
+ * Returns the Number of packets since last recorded loss*/
 unsigned int interp_ack_vect(u_char* hdr)
 {
        int hdrlen=((struct dccp_hdr*)hdr)->dccph_doff*4;
@@ -588,7 +520,6 @@ unsigned int interp_ack_vect(u_char* hdr)
 
        /*parse options*/
        while(optlen > 0){
-               len=*(opt+1);
 
                /*One byte options (no length)*/
                if(*opt< 32){
@@ -597,6 +528,13 @@ unsigned int interp_ack_vect(u_char* hdr)
                        continue;
                }
 
+               /*Check option length*/
+               len=*(opt+1);
+               if(len > optlen){
+                       dbgprintf(0, "Warning: Option would extend into packet data\n");
+                       return additional;
+               }
+
                /*Ack Vector Option*/
                if(*opt==38 || *opt==39){
                        tmp=len-2;
@@ -616,6 +554,10 @@ unsigned int interp_ack_vect(u_char* hdr)
                                if((*cur & 0xC0)==0x00){ //received packet
                                        bp+= (*cur & 0x3F)+1;
                                }
+
+                               if(((*cur& 0xC0)!= 0xC0) && ((*cur& 0xC0)!= 0x00) && ((*cur& 0xC0)!= 0x40)){
+                                       dbgprintf(1, "Warning: Invalid Ack Vector!! (Linux will handle poorly!)\n");
+                               }
                                tmp--;
                                cur++;
                        }
@@ -631,38 +573,31 @@ return additional;
 
 
 /* Setup Sequence Number Structure*/
-u_int32_t initialize_seq(struct seq_num **seq, __be16 source, __be32 initial)
+u_int32_t initialize_seq(struct host *seq, __be32 initial)
 {
-       /*allocate structure*/
-       *seq=(struct seq_num*)malloc(sizeof(struct seq_num));
-       if(*seq==NULL){
-               dbgprintf(0,"Can't Allocate Memory!\n");
-               exit(1);
-       }
-
        /*set default values*/
-       (*seq)->cur=0;
-       (*seq)->addr=source;
-       (*seq)->size=TBL_SZ;
+       seq->cur=0;
+       seq->size=TBL_SZ;
        
        /*allocate table*/
-       (*seq)->table=(struct tbl*)malloc(sizeof(struct tbl)*TBL_SZ);
-       if((*seq)->table==NULL){
+       seq->table=(struct tbl*)malloc(sizeof(struct tbl)*TBL_SZ);
+       if(seq->table==NULL){
                dbgprintf(0,"Can't Allocate Memory!\n");
                exit(1);
        }
 
        /*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;
+       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;
 }
 
 
 /*Convert Sequence Numbers*/
-u_int32_t add_new_seq(struct seq_num *seq, __be32 num, int size, enum dccp_pkt_type type)
+u_int32_t add_new_seq(struct host *seq, __be32 num, int size, enum dccp_pkt_type type)
 {
        int prev;
        if(seq==NULL){
@@ -670,10 +605,20 @@ u_int32_t add_new_seq(struct seq_num *seq, __be32 num, int size, enum dccp_pkt_t
                exit(1);
        }
        
+       if(seq->table==NULL){
+               dbgprintf(1, "Warning: Connection uninitialized\n");
+               return initialize_seq(seq, num);
+       }
+
        /*account for missing packets*/
+       if(num - seq->table[seq->cur].old +1 >=100){
+                       dbgprintf(1,"Missing more than 100 packets!\n");
+       }
        while(seq->table[seq->cur].old +1 < num && seq->table[seq->cur].old +1 > 0){
                prev=seq->cur;
-               dbgprintf(1,"Missing Packet: %X\n",seq->table[prev].new+1);
+               if(num - seq->table[seq->cur].old +1 <100){
+                       dbgprintf(1,"Missing Packet: %X\n",seq->table[prev].new+1);
+               }
                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;
@@ -705,13 +650,18 @@ return seq->table[seq->cur].new +1;
 
 
 /*Convert Ack Numbers*/
-u_int32_t convert_ack(struct seq_num *seq, __be32 num)
+u_int32_t convert_ack(struct host *seq, __be32 num)
 {
        if(seq==NULL){
                dbgprintf(0,"ERROR NULL POINTER!\n");
                exit(1);
        }
 
+       if(seq->table==NULL){
+               dbgprintf(1, "Warning: Connection uninitialized\n");
+               initialize_seq(seq, num);
+       }
+
        /*loop through table looking for the DCCP ack number*/
        for(int i=0; i < seq->size; i++){
                if(seq->table[i].old==num){
@@ -725,13 +675,18 @@ return 0;
 
 
 /* Get size of packet being acked*/
-int acked_packet_size(struct seq_num *seq, __be32 num)
+int acked_packet_size(struct host *seq, __be32 num)
 {
        if(seq==NULL){
                dbgprintf(0,"ERROR NULL POINTER!\n");
                exit(1);
        }
 
+       if(seq->table==NULL){
+               dbgprintf(1, "Warning: Connection uninitialized\n");
+               initialize_seq(seq, num);
+       }
+
        /*loop through table looking for the DCCP ack number*/
        for(int i=0; i < seq->size; i++){
                if(seq->table[i].old==num){
@@ -745,7 +700,7 @@ return 0;
 
 
 /*Ack Vector to SACK Option*/
-void ack_vect2sack(struct seq_num *seq, struct tcphdr *tcph, u_char* tcpopts, u_char* dccphdr, __be32 dccpack)
+void ack_vect2sack(struct host *seq, struct tcphdr *tcph, u_char* tcpopts, u_char* dccphdr, __be32 dccpack)
 {
        int hdrlen=((struct dccp_hdr*)dccphdr)->dccph_doff*4;
        int optlen;
@@ -769,7 +724,7 @@ void ack_vect2sack(struct seq_num *seq, struct tcphdr *tcph, u_char* tcpopts, u_
        opt=dccphdr + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
 
        /*setup tcp pointers*/
-       num_blocks=2;
+       num_blocks=4;
        *tcpopts=5;
        tlen=tcpopts+1;
        temp=tlen;
@@ -785,7 +740,6 @@ void ack_vect2sack(struct seq_num *seq, struct tcphdr *tcph, u_char* tcpopts, u_
 
        /*parse options*/
        while(optlen > 0){
-               len=*(opt+1);
 
                /*One byte options (no length)*/
                if(*opt< 32){
@@ -794,6 +748,12 @@ void ack_vect2sack(struct seq_num *seq, struct tcphdr *tcph, u_char* tcpopts, u_
                        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;