]> sjero.net Git - dccp2tcp/blob - dccp2tcp.c
bugfix for 6667c43df783 "Add warning about malformed ACK vectors"---I'm an idiot
[dccp2tcp] / dccp2tcp.c
1 /******************************************************************************
2 Author: Samuel Jero
3
4 Date: 7/2011
5
6 Description: Program to convert a DCCP flow to a TCP flow for DCCP analysis via
7                 tcptrace.
8
9 Notes:
10         1)CCID2 ONLY
11         2)DCCP MUST use 48 bit sequence numbers
12         3)Checksums are not computed (they are zeroed)
13         4)Only implements those packet types normally used in a session
14         5)DCCP Ack packets show up as TCP packets containing one byte
15         6)Very little error checking of packet headers
16 ******************************************************************************/
17 #include "dccp2tcp.h"
18
19
20 int debug=0;    /*set to 1 to turn on debugging information*/
21 int yellow=0;   /*tcptrace yellow line as currently acked packet*/
22 int green=0;    /*tcptrace green line as currently acked packet*/
23 int sack=0;             /*add TCP SACKS*/
24
25 pcap_t*                 in;                     /*libpcap input file discriptor*/
26 pcap_dumper_t   *out;           /*libpcap output file discriptor*/
27 struct connection *chead;       /*connection list*/
28
29
30
31 void PcapSavePacket(struct pcap_pkthdr *h, u_char *data);
32 void process_packets();
33 void handle_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes);
34 int convert_packet(struct packet *new, const struct const_packet* old);
35 unsigned int interp_ack_vect(u_char* hdr);
36 u_int32_t initialize_seq(struct host *seq, __be16 source, __be32 initial);
37 u_int32_t add_new_seq(struct host *seq, __be32 num, int size, enum dccp_pkt_type type);
38 u_int32_t convert_ack(struct host *seq, __be32 num);
39 int acked_packet_size(struct host *seq, __be32 num);
40 void ack_vect2sack(struct host *seq, struct tcphdr *tcph, u_char* tcpopts, u_char* dccphdr, __be32 dccpack);
41
42
43 /*Parse commandline options and open files*/
44 int main(int argc, char *argv[])
45 {
46         char ebuf[200];
47         char *erbuffer=ebuf;
48         char *dfile=NULL;
49         char *tfile=NULL;
50
51         /*parse commandline options*/
52         if(argc<3 || argc > 9){
53                 dbgprintf(0, "Usage: dccp2tcp dccp_file tcp_file [-d] [-y] [-g] [-s]\n");
54                 exit(1);
55         }
56
57         /*loop through commandline options*/
58         for(int i=1; i < argc; i++){
59                 if(argv[i][0]!='-'){
60                         if(dfile==NULL){ /*assign first non-dash argument to the dccp file*/
61                                 dfile=argv[i];
62                         }else{
63                                 if(tfile==NULL){
64                                         tfile=argv[i]; /*assign second non-dash argument to the dccp file*/
65                                 }else{
66                                         dbgprintf(0,"Usage: dccp2tcp dccp_file tcp_file [-d] [-y] [-g] [-s]\n");
67                                         exit(1);
68                                 }
69                         }
70                 }else{
71                         if(argv[i][1]=='d' && strlen(argv[i])==2){ /*debug option*/
72                                 debug++;
73                         }
74                         if(argv[i][1]=='y' && strlen(argv[i])==2){ /*yellow option*/
75                                 yellow=1;
76                         }
77                         if(argv[i][1]=='g' && strlen(argv[i])==2){ /*green option*/
78                                 green=1;
79                         }
80                         if(argv[i][1]=='s' && strlen(argv[i])==2){ /*sack option*/
81                                 sack++;
82                         }
83                 }
84         }
85         
86         if(dfile==NULL || tfile==NULL){
87                 dbgprintf(0,"Usage: dccp2tcp dccp_file tcp_file [-d] [-y] [-g] [-s]\n");
88                 exit(1);
89         }
90
91         /*all options validated*/
92
93         if(debug){
94                 dbgprintf(1,"Debug On\n");
95                 if(green){
96                         dbgprintf(1,"Tcptrace green line at highest acknowledgment\n");
97                 }else{
98                         dbgprintf(1,"Tcptrace green line at highest acknowledged acknowledgment\n");
99                 }
100                 if(yellow){
101                         dbgprintf(1,"Tcptrace yellow line at highest acknowledgment\n");
102                 }else{
103                         dbgprintf(1,"Tcptrace yellow line window value (a made up number)\n");
104                 }
105                 if(sack){
106                         dbgprintf(1,"Adding TCP SACKS\n");
107                 }
108                 dbgprintf(1,"Input file: %s\n", dfile);
109                 dbgprintf(1,"Output file: %s\n", tfile);
110         }
111
112         /*attempt to open input file*/
113         in=pcap_open_offline(dfile, erbuffer);
114         if(in==NULL){
115                 dbgprintf(0,"Error opening input file\n");
116                 exit(1);
117         }
118
119         /*attempt to open output file*/
120         out=pcap_dump_open(in,tfile);
121         if(out==NULL){
122                 dbgprintf(0,"Error opening output file\n");
123                 exit(1);
124         }
125
126         /*process packets*/
127         chead=NULL;
128         u_char *user=(u_char*)out;
129         pcap_loop(in, -1, handle_packet, user); 
130         
131         /*close files*/
132         pcap_close(in);
133         pcap_dump_close(out);
134 return 0;
135 }
136
137
138 /*call back function for pcap_loop--do basic packet handling*/
139 void handle_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
140 {
141         u_char                          *ndata;
142         struct pcap_pkthdr      nh;
143         int                                     link_type;
144         struct packet           new;
145         struct const_packet     old;
146
147         /*Determine the link type for this packet*/
148         link_type=pcap_datalink(in);
149
150         /*create new libpcap header*/
151         memcpy(&nh, h, sizeof(struct pcap_pkthdr));
152
153         /*Setup packet structs*/
154         old.h=h;
155         old.length=h->caplen;
156         old.data=bytes;
157         new.h=&nh;
158         new.length=MAX_PACKET;
159
160         /*create buffer for new packet*/
161         new.data=ndata=malloc(MAX_PACKET);
162         if(ndata==NULL){
163                 dbgprintf(0,"Error: Couldn't allocate Memory\n");
164                 exit(1);
165         }
166
167         /*make sure the packet is all zero*/
168         memset(new.data, 0, MAX_PACKET);
169         
170         /*do all the fancy conversions*/
171         if(!do_encap(link_type, &new, &old)){
172                 free(ndata);
173                 return;
174         }
175
176         /*save packet*/
177         pcap_dump(user,&nh, ndata);
178
179         free(ndata);
180 return;
181 }
182
183
184 /*do all the dccp to tcp conversions*/
185 int convert_packet(struct packet *new, const struct const_packet* old)
186 {       
187         struct tcphdr                           *tcph;
188         struct dccp_hdr                         *dccph;
189         struct dccp_hdr_ext             *dccphex;
190         struct dccp_hdr_ack_bits        *dccphack;
191         struct host                                     *h1=NULL;
192         struct host                                     *h2=NULL;
193         int                                             datalength;
194         int                                                     len=0;
195         const u_char*                           pd;
196         u_char*                                         npd;
197         u_char*                                         tcpopt;
198
199         /*Safety checks*/
200         if(!new || !old || !new->data || !old->data || !new->h || !old->h){
201                 dbgprintf(0,"Error:  Convert Packet Function given bad data!\n");
202                 exit(1);
203                 return 0;
204         }
205         if(old->length < sizeof(struct dccp_hdr) || new->length < sizeof(struct dccp_hdr)){
206                 dbgprintf(0, "Error: Convert Packet Function given packet of wrong size!\n");
207                 return 0;
208         }
209
210         /*cast header pointers*/
211         tcph=(struct tcphdr*)new->data;
212         tcpopt=new->data + sizeof(struct tcphdr);
213         dccph=(struct dccp_hdr*)old->data;
214         dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
215         dccphack=(struct dccp_hdr_ack_bits*)(old->data+ sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
216
217         dbgprintf(2,"Sequence Number: %llu\n", (unsigned long long)(((unsigned long)ntohs(dccph->dccph_seq)<<32) + ntohl(dccphex->dccph_seq_low)));
218
219         /*Get Hosts*/
220         if(get_host(new->src_id, new->dest_id, dccph->dccph_sport, dccph->dccph_dport, &h1, &h2)){
221                 dbgprintf(0,"Error: Can't Get Hosts!\n");
222                 return 0;
223         }
224         if(h1==NULL || h2==NULL){
225                 dbgprintf(0, "Error: Can't Get Hosts!\n");
226                 return 0;
227         }
228
229         /*determine data length*/
230         datalength=old->length - dccph->dccph_doff*4;
231         pd=old->data + dccph->dccph_doff*4;
232
233         /*set TCP standard features*/
234         tcph->source=dccph->dccph_sport;
235         tcph->dest=dccph->dccph_dport;
236         tcph->doff=5;
237         tcph->check=htonl(0);
238         tcph->urg_ptr=0;
239
240         /*Adjust TCP advertised window size*/
241         if(!yellow){
242                 tcph->window=htons(30000);
243         }
244
245         /*make changes by packet type*/
246         if(dccph->dccph_type==DCCP_PKT_REQUEST){//DCCP REQUEST -->TCP SYN
247                 dbgprintf(2,"Packet Type: Request\n");
248                 if(h1->state==INIT){
249                         if(yellow){
250                                 tcph->window=htons(0);
251                         }
252                         tcph->ack_seq=htonl(0);
253                         tcph->seq=htonl(initialize_seq(h1, dccph->dccph_sport, ntohl(dccphex->dccph_seq_low)));
254                         tcph->syn=1;
255                         tcph->ack=0;
256                         tcph->fin=0;
257                         tcph->rst=0;
258
259                         /* add Sack-permitted option, if relevant*/
260                         if(sack){
261                                 *tcpopt=4;
262                                 tcpopt++;
263                                 *tcpopt=2;
264                                 tcph->doff++;
265                         }
266
267                         /*calculate length*/
268                         len=tcph->doff*4;
269                 }
270         }
271
272         if(dccph->dccph_type==DCCP_PKT_RESPONSE){//DCCP RESPONSE-->TCP SYN,ACK
273                 dbgprintf(2,"Packet Type: Response\n");
274                 if(h2->state==OPEN && h1->state==INIT){
275                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
276                         if(yellow){
277                                 tcph->window=htons(0);
278                         }
279                         tcph->seq=htonl(initialize_seq(h1, dccph->dccph_sport, ntohl(dccphex->dccph_seq_low)));
280                         tcph->syn=1;
281                         tcph->ack=1;
282                         tcph->fin=0;
283                         tcph->rst=0;
284
285                         /* add Sack-permitted option, if relevant*/
286                         if(sack){
287                                 *tcpopt=4;
288                                 *(tcpopt+1)=2;
289                                 tcph->doff++;
290                         }
291
292                         /*calculate length*/
293                         len=tcph->doff*4;
294                 }
295         }
296
297         if(dccph->dccph_type==DCCP_PKT_DATA){//DCCP DATA----Never seen in packet capture
298                 dbgprintf(0,"DCCP Data packet not yet implemented\n");
299                 exit(1);
300         }
301
302         if(dccph->dccph_type==DCCP_PKT_DATAACK){//DCCP DATAACK-->TCP ACK with data
303                 dbgprintf(2,"Packet Type: DataAck\n");
304                 if(green){
305                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
306                 }else{
307                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
308                 }
309                 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),datalength, dccph->dccph_type));
310                 if(yellow){
311                         tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
312                 }
313                 if(sack){
314                         if(sack!=2 || interp_ack_vect((u_char*)dccph)){
315                                 ack_vect2sack(h2, tcph, tcpopt, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
316                         }
317                 }
318
319                 tcph->syn=0;
320                 tcph->ack=1;
321                 tcph->fin=0;
322                 tcph->rst=0;
323
324                 /*copy data*/
325                 npd=new->data + tcph->doff*4;
326                 memcpy(npd, pd, datalength);
327
328                 /*calculate length*/
329                 len= tcph->doff*4 + datalength;
330         }
331
332         if(dccph->dccph_type==DCCP_PKT_ACK){ //DCCP ACK -->TCP ACK with no data
333                 dbgprintf(2,"Packet Type: Ack\n");
334                 if(green){
335                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
336                 }else{
337                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
338                 }
339                 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
340                 if(yellow){
341                         tcph->window=htons(-interp_ack_vect((u_char*)dccph)*1400);
342                         if(-interp_ack_vect((u_char*)dccph)*1400 > 65535){
343                                 printf("Note: TCP Window Overflow @ %d.%d\n", (int)old->h->ts.tv_sec, (int)old->h->ts.tv_usec);
344                         }
345                 }
346                 if(sack){
347                         if(sack!=2 || interp_ack_vect((u_char*)dccph)){
348                                 ack_vect2sack(h2, tcph, tcpopt, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
349                         }
350                 }
351
352                 tcph->syn=0;
353                 tcph->ack=1;
354                 tcph->fin=0;
355                 tcph->rst=0;
356
357                 /*calculate length*/
358                 len=tcph->doff*4 + 1;
359         }
360
361         if(dccph->dccph_type==DCCP_PKT_CLOSEREQ){//DCCP CLOSEREQ----Never seen in packet capture
362                 dbgprintf(0,"DCCP CloseReq not yet implemented\n");
363                 exit(1);
364         }
365
366         if(dccph->dccph_type==DCCP_PKT_CLOSE){//DCCP CLOSE-->TCP FIN,ACK
367                 dbgprintf(2,"Packet Type: Close\n");
368                 update_state(h1,CLOSE);
369                 if(green){
370                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
371                 }else{
372                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
373                 }
374                 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
375                 if(yellow){
376                         tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
377                 }
378                 if(sack){
379                         if(sack!=2 || interp_ack_vect((u_char*)dccph)){
380                                 ack_vect2sack(h2, tcph, tcpopt, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
381                         }
382                 }
383
384                 tcph->syn=0;
385                 tcph->ack=1;
386                 tcph->fin=1;
387                 tcph->rst=0;
388
389                 /*calculate length*/
390                 len=tcph->doff*4;
391         }
392
393         if(dccph->dccph_type==DCCP_PKT_RESET){//DCCP RESET-->TCP FIN,ACK (only seen at end of connection as CLOSE ACK)
394                 if(h2->state==CLOSE){
395                         update_state(h1,CLOSE);
396                 }
397                 dbgprintf(2,"Packet Type: Reset\n");
398                 if(green){
399                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
400                 }else{
401                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
402                 }
403                 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
404                 if(yellow){
405                         tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
406                 }
407                 if(sack){
408                         if(sack!=2 || interp_ack_vect((u_char*)dccph)){
409                                 ack_vect2sack(h2, tcph, tcpopt, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
410                         }
411                 }
412
413                 tcph->syn=0;
414                 tcph->ack=1;
415                 tcph->fin=1;
416                 tcph->rst=0;
417
418                 /*calculate length*/
419                 len=tcph->doff*4;
420         }
421
422         if(dccph->dccph_type==DCCP_PKT_SYNC){//DCCP SYNC
423                 dbgprintf(2,"Packet Type: Sync\n");
424                 if(green){
425                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
426                 }else{
427                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
428                 }
429                 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),0,dccph->dccph_type));
430                 if(yellow){
431                         tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
432                 }else{
433                         tcph->window=htons(0);
434                 }
435                 if(sack){
436                         if(sack!=2 || interp_ack_vect((u_char*)dccph)){
437                                 ack_vect2sack(h2, tcph, tcpopt, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
438                         }
439                 }
440
441                 tcph->syn=0;
442                 tcph->ack=1;
443                 tcph->fin=0;
444                 tcph->rst=0;
445
446                 /*calculate length*/
447                 len=tcph->doff*4;
448         }
449
450         if(dccph->dccph_type==DCCP_PKT_SYNCACK){//DCCP SYNACK
451                 dbgprintf(2,"Packet Type: SyncAck\n");
452                 if(green){
453                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
454                 }else{
455                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
456                 }
457                 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),0,dccph->dccph_type));
458                 if(yellow){
459                         tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
460                 }else{
461                         tcph->window=htons(0);
462                 }
463                 if(sack){
464                         if(sack!=2 || interp_ack_vect((u_char*)dccph)){
465                                 ack_vect2sack(h2, tcph, tcpopt, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low));
466                         }
467                 }
468
469                 tcph->syn=0;
470                 tcph->ack=1;
471                 tcph->fin=0;
472                 tcph->rst=0;
473
474                 /*calculate length*/
475                 len=tcph->doff*4;
476         }
477
478         if(dccph->dccph_type==DCCP_PKT_INVALID){//DCCP INVALID----Never seen in packet capture
479                 dbgprintf(0,"Invalid DCCP Packet!!\n");
480                 return 0;
481         }
482
483         new->length=len;
484 return 1;
485 }
486
487
488 /*Parse Ack Vector Options
489  * Returns the Number of packets since last recorded loss*/
490 unsigned int interp_ack_vect(u_char* hdr)
491 {
492         int hdrlen=((struct dccp_hdr*)hdr)->dccph_doff*4;
493         //struct dccp_hdr_ext* e=(struct dccp_hdr_ext*)hdr + sizeof(struct dccp_hdr);
494         int optlen;
495         int len;
496         int tmp;
497         int bp=0;
498         int additional=0;
499         u_char* opt;
500         u_char* cur;
501
502         /*setup pointer to DCCP options and determine how long the options are*/
503         optlen=hdrlen-sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
504         opt=hdr + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
505
506         /*parse options*/
507         while(optlen > 0){
508                 len=*(opt+1);
509
510                 /*One byte options (no length)*/
511                 if(*opt< 32){
512                         optlen--;
513                         opt++;
514                         continue;
515                 }
516
517                 /*Ack Vector Option*/
518                 if(*opt==38 || *opt==39){
519                         tmp=len-2;
520                         cur=opt+2;
521                         /*loop through Vector*/
522                         while(tmp > 0){
523                                 /*ack vector works BACKWARDS through time*/
524
525                                 /*keep track of total packets recieved and if
526                                 a packet is lost, subtract all packets received
527                                 after that*/
528                                 if((*cur & 0xC0)==0xC0 || (*cur & 0xC0)==0x40){ //lost packet
529                                         bp+=(*cur & 0x3F)+1;
530                                         additional= -bp;
531                                 }
532                                         
533                                 if((*cur & 0xC0)==0x00){ //received packet
534                                         bp+= (*cur & 0x3F)+1;
535                                 }
536
537                                 if(((*cur& 0xC0)!= 0xC0) && ((*cur& 0xC0)!= 0x00) && ((*cur& 0xC0)!= 0x40)){
538                                         dbgprintf(1, "Warning: Invalid Ack Vector!! (Linux will handle poorly!) -- %X\n", *cur);
539                                 }
540                                 tmp--;
541                                 cur++;
542                         }
543                 }
544                 
545                 optlen-=len;
546                 opt+=len;
547         }
548
549         dbgprintf(2,"Ack vector adding: %i\n", additional);
550 return additional;
551 }
552
553
554 /* Setup Sequence Number Structure*/
555 u_int32_t initialize_seq(struct host *seq, __be16 source, __be32 initial)
556 {
557         /*set default values*/
558         seq->cur=0;
559         seq->size=TBL_SZ;
560         
561         /*allocate table*/
562         seq->table=(struct tbl*)malloc(sizeof(struct tbl)*TBL_SZ);
563         if(seq->table==NULL){
564                 dbgprintf(0,"Can't Allocate Memory!\n");
565                 exit(1);
566         }
567
568         /*add first sequence number*/
569         seq->table[0].old=initial;
570         seq->table[0].new=initial;
571         seq->table[0].type=DCCP_PKT_REQUEST;
572         seq->table[0].size=0;
573         update_state(seq,OPEN);
574 return initial;
575 }
576
577
578 /*Convert Sequence Numbers*/
579 u_int32_t add_new_seq(struct host *seq, __be32 num, int size, enum dccp_pkt_type type)
580 {
581         int prev;
582         if(seq==NULL){
583                 dbgprintf(0,"ERROR NULL POINTER!\n");
584                 exit(1);
585         }
586         
587         if(seq->table==NULL){
588                 dbgprintf(1, "Warning: Connection uninitialized\n");
589                 return initialize_seq(seq, 0, num);
590         }
591
592         /*account for missing packets*/
593         while(seq->table[seq->cur].old +1 < num && seq->table[seq->cur].old +1 > 0){
594                 prev=seq->cur;
595                 dbgprintf(1,"Missing Packet: %X\n",seq->table[prev].new+1);
596                 seq->cur=(seq->cur+1)%(seq->size);/*find next available table slot*/
597                 seq->table[seq->cur].old=seq->table[prev].old+1;
598                 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
599                 seq->table[seq->cur].size=size;
600                 seq->table[seq->cur].type=type;
601         }
602
603         prev=seq->cur;
604         seq->cur=(seq->cur+1)%(seq->size);/*find next available table slot*/
605         seq->table[seq->cur].old=num;
606         seq->table[seq->cur].size=size;
607         seq->table[seq->cur].type=type;
608         if(seq->table[prev].type==DCCP_PKT_REQUEST || seq->table[prev].type==DCCP_PKT_RESPONSE){
609                 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
610                 seq->table[seq->cur].size=1;
611                 return seq->table[prev].new + seq->table[prev].size+1;
612         }
613         if(type==DCCP_PKT_DATA || type==DCCP_PKT_DATAACK || type==DCCP_PKT_ACK){
614                 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
615                 return seq->table[seq->cur].new+1;
616         }
617         if(type==DCCP_PKT_SYNC || type==DCCP_PKT_SYNCACK){
618                 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
619                 return seq->table[seq->cur].new;
620         }
621         seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
622 return seq->table[seq->cur].new +1;
623 }
624
625
626 /*Convert Ack Numbers*/
627 u_int32_t convert_ack(struct host *seq, __be32 num)
628 {
629         if(seq==NULL){
630                 dbgprintf(0,"ERROR NULL POINTER!\n");
631                 exit(1);
632         }
633
634         if(seq->table==NULL){
635                 dbgprintf(1, "Warning: Connection uninitialized\n");
636                 initialize_seq(seq, 0, num);
637         }
638
639         /*loop through table looking for the DCCP ack number*/
640         for(int i=0; i < seq->size; i++){
641                 if(seq->table[i].old==num){
642                         return  seq->table[i].new + seq->table[i].size + 1; /*TCP acks the sequence number plus 1*/
643                 }
644         }
645         
646         dbgprintf(1, "Error: Address Not Found! looking for: %X\n", num);
647 return 0;
648 }
649
650
651 /* Get size of packet being acked*/
652 int acked_packet_size(struct host *seq, __be32 num)
653 {
654         if(seq==NULL){
655                 dbgprintf(0,"ERROR NULL POINTER!\n");
656                 exit(1);
657         }
658
659         if(seq->table==NULL){
660                 dbgprintf(1, "Warning: Connection uninitialized\n");
661                 initialize_seq(seq, 0, num);
662         }
663
664         /*loop through table looking for the DCCP ack number*/
665         for(int i=0; i < seq->size; i++){
666                 if(seq->table[i].old==num){
667                         return  seq->table[i].size;
668                 }
669         }
670         
671         dbgprintf(1, "Error: Address Not Found! looking for: %X\n", num);
672 return 0;
673 }
674
675
676 /*Ack Vector to SACK Option*/
677 void ack_vect2sack(struct host *seq, struct tcphdr *tcph, u_char* tcpopts, u_char* dccphdr, __be32 dccpack)
678 {
679         int hdrlen=((struct dccp_hdr*)dccphdr)->dccph_doff*4;
680         int optlen;
681         int len;
682         int tmp;
683         __be32 bp;
684         u_char* temp;
685         u_char* opt;
686         u_char* cur;
687         u_char* tlen;
688         u_int32_t bL=0;
689         u_int32_t bR;
690         u_int32_t* pL;
691         u_int32_t* pR;
692         int num_blocks;
693         int cont;
694         int isopt;
695         
696         /*setup pointer to DCCP options and determine how long the options are*/
697         optlen=hdrlen-sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
698         opt=dccphdr + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
699
700         /*setup tcp pointers*/
701         num_blocks=4;
702         *tcpopts=5;
703         tlen=tcpopts+1;
704         temp=tlen;
705         temp++;
706         pL=(u_int32_t*)temp;
707         pR=pL+1;
708
709         /*setup tcp control variables*/
710         bp=dccpack;
711         cont=0;
712         *tlen=2;
713         isopt=0;
714
715         /*parse options*/
716         while(optlen > 0){
717                 len=*(opt+1);
718
719                 /*One byte options (no length)*/
720                 if(*opt< 32){
721                         optlen--;
722                         opt++;
723                         continue;
724                 }
725
726                 /*Ack Vector Option*/
727                 if(*opt==38 || *opt==39){
728                         tmp=len-2;
729                         cur=opt+2;
730                         /*loop through Vector*/
731                         while(tmp > 0){
732                                 /*ack vector works BACKWARDS through time*/
733
734                                 if((*cur & 0xC0)==0xC0 || (*cur & 0xC0)==0x40){ //lost packet
735                                         if(cont){ /*end a SACK run, if one is started*/
736                                                 bR=convert_ack(seq, bp);
737                                                 cont=0;
738                                                 num_blocks--;
739                                                 *pR=htonl(bR);
740                                                 *pL=htonl(bL);
741                                                 tcph->doff+=2;
742                                                 *tlen+=8;
743                                                 pL=pR+1;
744                                                 pR=pL+1;                        
745                                         }
746                                         bp= bp - (*cur & 0x3F)- 1;
747                                 }
748                                         
749                                 if((*cur & 0xC0)==0x00){ //received packet
750                                         if(!cont){ /*if no SACK run and we can start another one, do so*/
751                                                 if(num_blocks>0){
752                                                         bL=convert_ack(seq, bp);
753                                                         isopt=1;
754                                                         cont=1;
755
756                                                 }
757                                         }
758                                         bp =  bp -(*cur & 0x3F)- 1;
759                                 }
760                                 tmp--;
761                                 cur++;
762                         }
763                 }
764                 
765                 optlen-=len;
766                 opt+=len;
767         }
768
769         /*if we are in the middle of a SACK run, close it*/
770         if(cont){
771                 bR=convert_ack(seq, bp);
772                 *pR=htonl(bR);
773                 *pL=htonl(bL);
774                 tcph->doff+=2;
775                 *tlen+=8;
776                 cont=0;
777         }
778
779         /*adjust length if the option is actually added*/
780         if(isopt){
781                 tcph->doff+=1;
782         }
783 return;
784 }
785
786 /*Debug Printf*/
787 void dbgprintf(int level, const char *fmt, ...)
788 {
789     va_list args;
790     if(debug>=level){
791         va_start(args, fmt);
792         vfprintf(stderr, fmt, args);
793         va_end(args);
794     }
795 }