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