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