]> sjero.net Git - dccp2tcp/blob - dccp2tcp.c
Keep debug output from slowing program down after massive losses
[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, __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) + sizeof(struct dccp_hdr_ext)) || new->length < sizeof(struct dccp_hdr)){
206                 dbgprintf(0, "Error: DCCP Packet Too short!\n");
207                 return 0;
208         }
209
210         /*cast header pointers*/
211         tcph=(struct tcphdr*)new->data;
212         dccph=(struct dccp_hdr*)old->data;
213         dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
214         dccphack=(struct dccp_hdr_ack_bits*)(old->data+ sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
215
216         dbgprintf(2,"Sequence Number: %llu\n", (unsigned long long)(((unsigned long)ntohs(dccph->dccph_seq)<<32) + ntohl(dccphex->dccph_seq_low)));
217
218         /*Get Hosts*/
219         if(get_host(new->src_id, new->dest_id, dccph->dccph_sport, dccph->dccph_dport, &h1, &h2)){
220                 dbgprintf(0,"Error: Can't Get Hosts!\n");
221                 return 0;
222         }
223         if(h1==NULL || h2==NULL){
224                 dbgprintf(0, "Error: Can't Get Hosts!\n");
225                 return 0;
226         }
227
228         /*Ensure packet is at least as large as DCCP header*/
229         if(old->length < dccph->dccph_doff*4){
230                 dbgprintf(0, "Error: DCCP Header truncated\n");
231                 return 0;
232         }
233         if(dccph->dccph_type!=DCCP_PKT_DATA &&
234                         old->length < (sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) +
235                         sizeof(struct dccp_hdr_ack_bits))){
236                 dbgprintf(0, "Error: DCCP Packet Too short!\n");
237         }
238
239         /*determine data length*/
240         datalength=old->length - dccph->dccph_doff*4;
241         pd=old->data + dccph->dccph_doff*4;
242
243         /*set TCP standard features*/
244         tcph->source=dccph->dccph_sport;
245         tcph->dest=dccph->dccph_dport;
246         tcph->doff=5;
247         tcph->check=htonl(0);
248         tcph->urg_ptr=0;
249
250         /*Adjust TCP advertised window size*/
251         if(!yellow){
252                 tcph->window=htons(30000);
253         }
254
255         /*make changes by packet type*/
256         if(dccph->dccph_type==DCCP_PKT_REQUEST){//DCCP REQUEST -->TCP SYN
257                 dbgprintf(2,"Packet Type: Request\n");
258                 if(h1->state==INIT){
259                         if(yellow){
260                                 tcph->window=htons(0);
261                         }
262                         tcph->ack_seq=htonl(0);
263                         tcph->seq=htonl(initialize_seq(h1, ntohl(dccphex->dccph_seq_low)));
264                         tcph->syn=1;
265                         tcph->ack=0;
266                         tcph->fin=0;
267                         tcph->rst=0;
268
269                         /* add Sack-permitted option, if relevant*/
270                         if(sack){
271                                 tcpopt=(u_char*)(new->data + tcph->doff*4);
272                                 *tcpopt=4;
273                                 tcpopt++;
274                                 *tcpopt=2;
275                                 tcph->doff++;
276                         }
277
278                         /*calculate length*/
279                         len=tcph->doff*4;
280                 }
281         }
282
283         if(dccph->dccph_type==DCCP_PKT_RESPONSE){//DCCP RESPONSE-->TCP SYN,ACK
284                 dbgprintf(2,"Packet Type: Response\n");
285                 if(h2->state==OPEN && h1->state==INIT){
286                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
287                         if(yellow){
288                                 tcph->window=htons(0);
289                         }
290                         tcph->seq=htonl(initialize_seq(h1, ntohl(dccphex->dccph_seq_low)));
291                         tcph->syn=1;
292                         tcph->ack=1;
293                         tcph->fin=0;
294                         tcph->rst=0;
295
296                         /* add Sack-permitted option, if relevant*/
297                         if(sack){
298                                 tcpopt=(u_char*)(new->data + tcph->doff*4);
299                                 *tcpopt=4;
300                                 *(tcpopt+1)=2;
301                                 tcph->doff++;
302                         }
303
304                         /*calculate length*/
305                         len=tcph->doff*4;
306                 }
307         }
308
309         if(dccph->dccph_type==DCCP_PKT_DATA){//DCCP DATA----Never seen in packet capture
310                 dbgprintf(0,"DCCP Data packet not yet implemented\n");
311                 exit(1);
312         }
313
314         if(dccph->dccph_type==DCCP_PKT_DATAACK){//DCCP DATAACK-->TCP ACK with data
315                 dbgprintf(2,"Packet Type: DataAck\n");
316                 if(green){
317                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
318                 }else{
319                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
320                 }
321                 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),datalength, dccph->dccph_type));
322                 if(yellow){
323                         tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
324                 }
325                 if(sack){
326                         if(sack!=2 || interp_ack_vect((u_char*)dccph)){
327                                 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
328                         }
329                 }
330
331                 tcph->syn=0;
332                 tcph->ack=1;
333                 tcph->fin=0;
334                 tcph->rst=0;
335
336                 /*copy data*/
337                 npd=new->data + tcph->doff*4;
338                 memcpy(npd, pd, datalength);
339
340                 /*calculate length*/
341                 len= tcph->doff*4 + datalength;
342         }
343
344         if(dccph->dccph_type==DCCP_PKT_ACK){ //DCCP ACK -->TCP ACK with no data
345                 dbgprintf(2,"Packet Type: Ack\n");
346                 if(green){
347                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
348                 }else{
349                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
350                 }
351                 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
352                 if(yellow){
353                         tcph->window=htons(-interp_ack_vect((u_char*)dccph)*1400);
354                         if(-interp_ack_vect((u_char*)dccph)*1400 > 65535){
355                                 printf("Note: TCP Window Overflow @ %d.%d\n", (int)old->h->ts.tv_sec, (int)old->h->ts.tv_usec);
356                         }
357                 }
358                 if(sack){
359                         if(sack!=2 || interp_ack_vect((u_char*)dccph)){
360                                 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
361                         }
362                 }
363
364                 tcph->syn=0;
365                 tcph->ack=1;
366                 tcph->fin=0;
367                 tcph->rst=0;
368
369                 /*calculate length*/
370                 len=tcph->doff*4 + 1;
371         }
372
373         if(dccph->dccph_type==DCCP_PKT_CLOSEREQ){//DCCP CLOSEREQ----Never seen in packet capture
374                 dbgprintf(0,"DCCP CloseReq not yet implemented\n");
375                 exit(1);
376         }
377
378         if(dccph->dccph_type==DCCP_PKT_CLOSE){//DCCP CLOSE-->TCP FIN,ACK
379                 dbgprintf(2,"Packet Type: Close\n");
380                 update_state(h1,CLOSE);
381                 if(green){
382                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
383                 }else{
384                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
385                 }
386                 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
387                 if(yellow){
388                         tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
389                 }
390                 if(sack){
391                         if(sack!=2 || interp_ack_vect((u_char*)dccph)){
392                                 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
393                         }
394                 }
395
396                 tcph->syn=0;
397                 tcph->ack=1;
398                 tcph->fin=1;
399                 tcph->rst=0;
400
401                 /*calculate length*/
402                 len=tcph->doff*4;
403         }
404
405         if(dccph->dccph_type==DCCP_PKT_RESET){//DCCP RESET-->TCP FIN,ACK (only seen at end of connection as CLOSE ACK)
406                 if(h2->state==CLOSE){
407                         update_state(h1,CLOSE);
408                 }
409                 dbgprintf(2,"Packet Type: Reset\n");
410                 if(green){
411                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
412                 }else{
413                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
414                 }
415                 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
416                 if(yellow){
417                         tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
418                 }
419                 if(sack){
420                         if(sack!=2 || interp_ack_vect((u_char*)dccph)){
421                                 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
422                         }
423                 }
424
425                 tcph->syn=0;
426                 tcph->ack=1;
427                 tcph->fin=1;
428                 tcph->rst=0;
429
430                 /*calculate length*/
431                 len=tcph->doff*4;
432         }
433
434         if(dccph->dccph_type==DCCP_PKT_SYNC){//DCCP SYNC
435                 dbgprintf(2,"Packet Type: Sync\n");
436                 if(green){
437                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
438                 }else{
439                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
440                 }
441                 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),0,dccph->dccph_type));
442                 if(yellow){
443                         tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
444                 }else{
445                         tcph->window=htons(0);
446                 }
447                 if(sack){
448                         if(sack!=2 || interp_ack_vect((u_char*)dccph)){
449                                 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
450                         }
451                 }
452
453                 tcph->syn=0;
454                 tcph->ack=1;
455                 tcph->fin=0;
456                 tcph->rst=0;
457
458                 /*calculate length*/
459                 len=tcph->doff*4;
460         }
461
462         if(dccph->dccph_type==DCCP_PKT_SYNCACK){//DCCP SYNACK
463                 dbgprintf(2,"Packet Type: SyncAck\n");
464                 if(green){
465                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
466                 }else{
467                         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
468                 }
469                 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),0,dccph->dccph_type));
470                 if(yellow){
471                         tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
472                 }else{
473                         tcph->window=htons(0);
474                 }
475                 if(sack){
476                         if(sack!=2 || interp_ack_vect((u_char*)dccph)){
477                                 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low));
478                         }
479                 }
480
481                 tcph->syn=0;
482                 tcph->ack=1;
483                 tcph->fin=0;
484                 tcph->rst=0;
485
486                 /*calculate length*/
487                 len=tcph->doff*4;
488         }
489
490         if(dccph->dccph_type==DCCP_PKT_INVALID){//DCCP INVALID----Never seen in packet capture
491                 dbgprintf(0,"Invalid DCCP Packet!!\n");
492                 return 0;
493         }
494
495         new->length=len;
496 return 1;
497 }
498
499
500 /*Parse Ack Vector Options
501  * Returns the Number of packets since last recorded loss*/
502 unsigned int interp_ack_vect(u_char* hdr)
503 {
504         int hdrlen=((struct dccp_hdr*)hdr)->dccph_doff*4;
505         //struct dccp_hdr_ext* e=(struct dccp_hdr_ext*)hdr + sizeof(struct dccp_hdr);
506         int optlen;
507         int len;
508         int tmp;
509         int bp=0;
510         int additional=0;
511         u_char* opt;
512         u_char* cur;
513
514         /*setup pointer to DCCP options and determine how long the options are*/
515         optlen=hdrlen-sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
516         opt=hdr + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
517
518         /*parse options*/
519         while(optlen > 0){
520
521                 /*One byte options (no length)*/
522                 if(*opt< 32){
523                         optlen--;
524                         opt++;
525                         continue;
526                 }
527
528                 /*Check option length*/
529                 len=*(opt+1);
530                 if(len > optlen){
531                         dbgprintf(0, "Warning: Option would extend into packet data\n");
532                         return additional;
533                 }
534
535                 /*Ack Vector Option*/
536                 if(*opt==38 || *opt==39){
537                         tmp=len-2;
538                         cur=opt+2;
539                         /*loop through Vector*/
540                         while(tmp > 0){
541                                 /*ack vector works BACKWARDS through time*/
542
543                                 /*keep track of total packets recieved and if
544                                 a packet is lost, subtract all packets received
545                                 after that*/
546                                 if((*cur & 0xC0)==0xC0 || (*cur & 0xC0)==0x40){ //lost packet
547                                         bp+=(*cur & 0x3F)+1;
548                                         additional= -bp;
549                                 }
550                                         
551                                 if((*cur & 0xC0)==0x00){ //received packet
552                                         bp+= (*cur & 0x3F)+1;
553                                 }
554
555                                 if(((*cur& 0xC0)!= 0xC0) && ((*cur& 0xC0)!= 0x00) && ((*cur& 0xC0)!= 0x40)){
556                                         dbgprintf(1, "Warning: Invalid Ack Vector!! (Linux will handle poorly!)\n");
557                                 }
558                                 tmp--;
559                                 cur++;
560                         }
561                 }
562                 
563                 optlen-=len;
564                 opt+=len;
565         }
566
567         dbgprintf(2,"Ack vector adding: %i\n", additional);
568 return additional;
569 }
570
571
572 /* Setup Sequence Number Structure*/
573 u_int32_t initialize_seq(struct host *seq, __be32 initial)
574 {
575         /*set default values*/
576         seq->cur=0;
577         seq->size=TBL_SZ;
578         
579         /*allocate table*/
580         seq->table=(struct tbl*)malloc(sizeof(struct tbl)*TBL_SZ);
581         if(seq->table==NULL){
582                 dbgprintf(0,"Can't Allocate Memory!\n");
583                 exit(1);
584         }
585
586         /*add first sequence number*/
587         seq->table[0].old=initial;
588         seq->table[0].new=initial;
589         seq->table[0].type=DCCP_PKT_REQUEST;
590         seq->table[0].size=0;
591         update_state(seq,OPEN);
592 return initial;
593 }
594
595
596 /*Convert Sequence Numbers*/
597 u_int32_t add_new_seq(struct host *seq, __be32 num, int size, enum dccp_pkt_type type)
598 {
599         int prev;
600         if(seq==NULL){
601                 dbgprintf(0,"ERROR NULL POINTER!\n");
602                 exit(1);
603         }
604         
605         if(seq->table==NULL){
606                 dbgprintf(1, "Warning: Connection uninitialized\n");
607                 return initialize_seq(seq, num);
608         }
609
610         /*account for missing packets*/
611         if(num - seq->table[seq->cur].old +1 >=100){
612                         dbgprintf(1,"Missing more than 100 packets!\n");
613         }
614         while(seq->table[seq->cur].old +1 < num && seq->table[seq->cur].old +1 > 0){
615                 prev=seq->cur;
616                 if(num - seq->table[seq->cur].old +1 <100){
617                         dbgprintf(1,"Missing Packet: %X\n",seq->table[prev].new+1);
618                 }
619                 seq->cur=(seq->cur+1)%(seq->size);/*find next available table slot*/
620                 seq->table[seq->cur].old=seq->table[prev].old+1;
621                 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
622                 seq->table[seq->cur].size=size;
623                 seq->table[seq->cur].type=type;
624         }
625
626         prev=seq->cur;
627         seq->cur=(seq->cur+1)%(seq->size);/*find next available table slot*/
628         seq->table[seq->cur].old=num;
629         seq->table[seq->cur].size=size;
630         seq->table[seq->cur].type=type;
631         if(seq->table[prev].type==DCCP_PKT_REQUEST || seq->table[prev].type==DCCP_PKT_RESPONSE){
632                 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
633                 seq->table[seq->cur].size=1;
634                 return seq->table[prev].new + seq->table[prev].size+1;
635         }
636         if(type==DCCP_PKT_DATA || type==DCCP_PKT_DATAACK || type==DCCP_PKT_ACK){
637                 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
638                 return seq->table[seq->cur].new+1;
639         }
640         if(type==DCCP_PKT_SYNC || type==DCCP_PKT_SYNCACK){
641                 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
642                 return seq->table[seq->cur].new;
643         }
644         seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
645 return seq->table[seq->cur].new +1;
646 }
647
648
649 /*Convert Ack Numbers*/
650 u_int32_t convert_ack(struct host *seq, __be32 num)
651 {
652         if(seq==NULL){
653                 dbgprintf(0,"ERROR NULL POINTER!\n");
654                 exit(1);
655         }
656
657         if(seq->table==NULL){
658                 dbgprintf(1, "Warning: Connection uninitialized\n");
659                 initialize_seq(seq, num);
660         }
661
662         /*loop through table looking for the DCCP ack number*/
663         for(int i=0; i < seq->size; i++){
664                 if(seq->table[i].old==num){
665                         return  seq->table[i].new + seq->table[i].size + 1; /*TCP acks the sequence number plus 1*/
666                 }
667         }
668         
669         dbgprintf(1, "Error: Address Not Found! looking for: %X\n", num);
670 return 0;
671 }
672
673
674 /* Get size of packet being acked*/
675 int acked_packet_size(struct host *seq, __be32 num)
676 {
677         if(seq==NULL){
678                 dbgprintf(0,"ERROR NULL POINTER!\n");
679                 exit(1);
680         }
681
682         if(seq->table==NULL){
683                 dbgprintf(1, "Warning: Connection uninitialized\n");
684                 initialize_seq(seq, num);
685         }
686
687         /*loop through table looking for the DCCP ack number*/
688         for(int i=0; i < seq->size; i++){
689                 if(seq->table[i].old==num){
690                         return  seq->table[i].size;
691                 }
692         }
693         
694         dbgprintf(1, "Error: Address Not Found! looking for: %X\n", num);
695 return 0;
696 }
697
698
699 /*Ack Vector to SACK Option*/
700 void ack_vect2sack(struct host *seq, struct tcphdr *tcph, u_char* tcpopts, u_char* dccphdr, __be32 dccpack)
701 {
702         int hdrlen=((struct dccp_hdr*)dccphdr)->dccph_doff*4;
703         int optlen;
704         int len;
705         int tmp;
706         __be32 bp;
707         u_char* temp;
708         u_char* opt;
709         u_char* cur;
710         u_char* tlen;
711         u_int32_t bL=0;
712         u_int32_t bR;
713         u_int32_t* pL;
714         u_int32_t* pR;
715         int num_blocks;
716         int cont;
717         int isopt;
718         
719         /*setup pointer to DCCP options and determine how long the options are*/
720         optlen=hdrlen-sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
721         opt=dccphdr + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
722
723         /*setup tcp pointers*/
724         num_blocks=4;
725         *tcpopts=5;
726         tlen=tcpopts+1;
727         temp=tlen;
728         temp++;
729         pL=(u_int32_t*)temp;
730         pR=pL+1;
731
732         /*setup tcp control variables*/
733         bp=dccpack;
734         cont=0;
735         *tlen=2;
736         isopt=0;
737
738         /*parse options*/
739         while(optlen > 0){
740
741                 /*One byte options (no length)*/
742                 if(*opt< 32){
743                         optlen--;
744                         opt++;
745                         continue;
746                 }
747
748                 len=*(opt+1);
749                 if(len > optlen){
750                         dbgprintf(0, "Warning: Option would extend into packet data\n");
751                         break;
752                 }
753
754                 /*Ack Vector Option*/
755                 if(*opt==38 || *opt==39){
756                         tmp=len-2;
757                         cur=opt+2;
758                         /*loop through Vector*/
759                         while(tmp > 0){
760                                 /*ack vector works BACKWARDS through time*/
761
762                                 if((*cur & 0xC0)==0xC0 || (*cur & 0xC0)==0x40){ //lost packet
763                                         if(cont){ /*end a SACK run, if one is started*/
764                                                 bR=convert_ack(seq, bp);
765                                                 cont=0;
766                                                 num_blocks--;
767                                                 *pR=htonl(bR);
768                                                 *pL=htonl(bL);
769                                                 tcph->doff+=2;
770                                                 *tlen+=8;
771                                                 pL=pR+1;
772                                                 pR=pL+1;                        
773                                         }
774                                         bp= bp - (*cur & 0x3F)- 1;
775                                 }
776                                         
777                                 if((*cur & 0xC0)==0x00){ //received packet
778                                         if(!cont){ /*if no SACK run and we can start another one, do so*/
779                                                 if(num_blocks>0){
780                                                         bL=convert_ack(seq, bp);
781                                                         isopt=1;
782                                                         cont=1;
783
784                                                 }
785                                         }
786                                         bp =  bp -(*cur & 0x3F)- 1;
787                                 }
788                                 tmp--;
789                                 cur++;
790                         }
791                 }
792                 
793                 optlen-=len;
794                 opt+=len;
795         }
796
797         /*if we are in the middle of a SACK run, close it*/
798         if(cont){
799                 bR=convert_ack(seq, bp);
800                 *pR=htonl(bR);
801                 *pL=htonl(bL);
802                 tcph->doff+=2;
803                 *tlen+=8;
804                 cont=0;
805         }
806
807         /*adjust length if the option is actually added*/
808         if(isopt){
809                 tcph->doff+=1;
810         }
811 return;
812 }
813
814 /*Debug Printf*/
815 void dbgprintf(int level, const char *fmt, ...)
816 {
817     va_list args;
818     if(debug>=level){
819         va_start(args, fmt);
820         vfprintf(stderr, fmt, args);
821         va_end(args);
822     }
823 }