]> sjero.net Git - dccp2tcp/blob - dccp2tcp.c
Cleanup types throughout code
[dccp2tcp] / dccp2tcp.c
1 /******************************************************************************
2 Utility to convert a DCCP flow to a TCP flow for DCCP analysis via
3                 tcptrace.
4
5 Copyright (C) 2013  Samuel Jero <sj323707@ohio.edu>
6
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20 Author: Samuel Jero <sj323707@ohio.edu>
21 Date: 02/2013
22
23 Notes:
24         1)DCCP MUST use 48 bit sequence numbers
25         2)DCCP Ack packets show up as TCP packets containing one byte
26 ******************************************************************************/
27 #include "dccp2tcp.h"
28
29
30 #define DCCP2TCP_VERSION 1.6
31 #define COPYRIGHT_YEAR 2013
32
33
34 int debug=0;    /*set to 1 to turn on debugging information*/
35 int yellow=0;   /*tcptrace yellow line as currently acked packet*/
36 int green=0;    /*tcptrace green line as currently acked packet*/
37 int sack=0;             /*add TCP SACKS*/
38
39
40 pcap_t*                 in;                     /*libpcap input file discriptor*/
41 pcap_dumper_t   *out;           /*libpcap output file discriptor*/
42 struct connection *chead;       /*connection list*/
43
44
45 void handle_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes);
46 int handle_request(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2);
47 int handle_response(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2);
48 int handle_dataack(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2);
49 int handle_ack(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2);
50 int handle_closereq(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2);
51 int handle_close(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2);
52 int handle_reset(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2);
53 int handle_sync(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2);
54 int handle_syncack(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2);
55 int handle_data(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2);
56 int parse_options(const u_char* opt_start, int len, struct hcon* A, struct hcon* B);
57 int process_feature(const u_char* feat, int len, int confirm, int L, struct hcon* A, struct hcon* B);
58 void ack_vect2sack(struct hcon *seq, struct tcphdr *tcph, u_char* tcpopts, u_char* dccphdr,
59                                 d_seq_num dccpack, struct hcon* o_hcn);
60 void version();
61 void usage();
62
63
64 /*Parse commandline options and open files*/
65 int main(int argc, char *argv[])
66 {
67         char ebuf[200];
68         char *erbuffer=ebuf;
69         char *dfile=NULL;
70         char *tfile=NULL;
71
72         /*parse commandline options*/
73         if(argc > 9){
74                 usage();
75         }
76
77         /*loop through commandline options*/
78         for(int i=1; i < argc; i++){
79                 if(argv[i][0]!='-' || (argv[i][0]=='-' && strlen(argv[i])==1)){
80                         if(dfile==NULL  || argv[i][0]=='-'){
81                                 /*assign first non-dash (or only dash) argument to the dccp file*/
82                                 dfile=argv[i];
83                         }else{
84                                 if(tfile==NULL){
85                                         tfile=argv[i]; /*assign second non-dash argument to the dccp file*/
86                                 }else{
87                                         usage();
88                                 }
89                         }
90                 }else{
91                         if(argv[i][1]=='d' && strlen(argv[i])==2){ /* -d */
92                                 debug++;
93                         }
94                         if(argv[i][1]=='y' && strlen(argv[i])==2){ /* -y */
95                                 yellow=1;
96                         }
97                         if(argv[i][1]=='g' && strlen(argv[i])==2){ /* -g */
98                                 green=1;
99                         }
100                         if(argv[i][1]=='s' && strlen(argv[i])==2){ /* -s */
101                                 sack++;
102                         }
103                         if(argv[i][1]=='h' && strlen(argv[i])==2){ /* -h */
104                                 usage();
105                         }
106                         if(argv[i][1]=='V' && strlen(argv[i])==2){ /* -V */
107                                 version();
108                         }
109                 }
110         }
111         
112         if(dfile==NULL || tfile==NULL){
113                 usage();
114         }
115
116         /*all options validated*/
117
118         if(debug){
119                 dbgprintf(1,"Debug On\n");
120                 if(green){
121                         dbgprintf(1,"Tcptrace green line at highest acknowledgment\n");
122                 }else{
123                         dbgprintf(1,"Tcptrace green line at highest acknowledged acknowledgment\n");
124                 }
125                 if(yellow){
126                         dbgprintf(1,"Tcptrace yellow line at highest acknowledgment\n");
127                 }else{
128                         dbgprintf(1,"Tcptrace yellow line window value (a made up number)\n");
129                 }
130                 if(sack){
131                         dbgprintf(1,"Adding TCP SACKS\n");
132                 }
133                 dbgprintf(1,"Input file: %s\n", dfile);
134                 dbgprintf(1,"Output file: %s\n", tfile);
135         }
136
137         /*attempt to open input file*/
138         in=pcap_open_offline(dfile, erbuffer);
139         if(in==NULL){
140                 dbgprintf(0,"Error opening input file\n");
141                 exit(1);
142         }
143
144         /*attempt to open output file*/
145         out=pcap_dump_open(in,tfile);
146         if(out==NULL){
147                 dbgprintf(0,"Error opening output file\n");
148                 exit(1);
149         }
150
151         /*process packets*/
152         chead=NULL;
153         u_char *user=(u_char*)out;
154         pcap_loop(in, -1, handle_packet, user); 
155         
156         /*close files*/
157         pcap_close(in);
158         pcap_dump_close(out);
159
160         /*Delete all connections*/
161         cleanup_connections();
162 return 0;
163 }
164
165
166 /*call back function for pcap_loop--do basic packet handling*/
167 void handle_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
168 {
169         u_char                          *ndata;
170         struct pcap_pkthdr      nh;
171         int                                     link_type;
172         struct packet           new;
173         struct const_packet     old;
174
175         /*Determine the link type for this packet*/
176         link_type=pcap_datalink(in);
177
178         /*create new libpcap header*/
179         memcpy(&nh, h, sizeof(struct pcap_pkthdr));
180
181         /*Setup packet structs*/
182         old.h=h;
183         old.length=h->caplen;
184         old.data=bytes;
185         old.dest_id=NULL;
186         old.src_id=NULL;
187         new.h=&nh;
188         new.length=MAX_PACKET;
189         new.dest_id=NULL;
190         new.src_id=NULL;
191
192         /*create buffer for new packet*/
193         new.data=ndata=malloc(MAX_PACKET);
194         if(ndata==NULL){
195                 dbgprintf(0,"Error: Couldn't allocate Memory\n");
196                 exit(1);
197         }
198
199         /*make sure the packet is all zero*/
200         memset(new.data, 0, MAX_PACKET);
201         
202         /*do all the fancy conversions*/
203         if(!do_encap(link_type, &new, &old)){
204                 free(ndata);
205                 return;
206         }
207
208         /*save packet*/
209         pcap_dump(user,&nh, ndata);
210
211         free(ndata);
212 return;
213 }
214
215 /*do all the dccp to tcp conversions*/
216 int convert_packet(struct packet *new, const struct const_packet* old)
217 {
218         struct tcphdr                           *tcph;
219         struct dccp_hdr                         *dccph;
220         struct dccp_hdr_ext             *dccphex;
221         struct hcon                                     *h1=NULL;
222         struct hcon                                     *h2=NULL;
223
224         /*Safety checks*/
225         if(!new || !old || !new->data || !old->data || !new->h || !old->h){
226                 dbgprintf(0,"Error:  Convert Packet Function given bad data!\n");
227                 exit(1);
228                 return 0;
229         }
230         if(old->length < (sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext))
231                                                                                                 || new->length < sizeof(struct dccp_hdr)){
232                 dbgprintf(0, "Error: DCCP Packet Too short!\n");
233                 return 0;
234         }
235
236         /*cast header pointers*/
237         tcph=(struct tcphdr*)new->data;
238         dccph=(struct dccp_hdr*)old->data;
239         dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
240
241         dbgprintf(2,"Sequence Number: %llu\n", (unsigned long long)
242                         (((unsigned long)ntohs(dccph->dccph_seq)<<32) + ntohl(dccphex->dccph_seq_low)));
243
244         /*Ensure packet is at least as large as DCCP header*/
245         if(old->length < dccph->dccph_doff*4){
246                 dbgprintf(0, "Error: DCCP Header truncated\n");
247                 return 0;
248         }
249
250         /*Get Hosts*/
251         if(get_host(new->src_id, new->dest_id, new->id_len, dccph->dccph_sport,
252                         dccph->dccph_dport, dccph->dccph_type,&h1, &h2)){
253                 dbgprintf(0,"Error: Can't Get Hosts!\n");
254                 return 0;
255         }
256         if(h1==NULL || h2==NULL){
257                 dbgprintf(0, "Error: Can't Get Hosts!\n");
258                 return 0;
259         }
260         if(h1->state==IGNORE || h2->state==IGNORE){
261                 dbgprintf(2, "Ignoring packet between %i and %i\n",
262                                                 ntohs(dccph->dccph_sport), ntohs(dccph->dccph_dport));
263                 return 0;
264         }
265
266         /*set TCP standard features*/
267         tcph->source=dccph->dccph_sport;
268         tcph->dest=dccph->dccph_dport;
269         tcph->doff=5;
270         tcph->check=htonl(0);
271         tcph->urg_ptr=0;
272
273         /*Adjust TCP advertised window size*/
274         if(!yellow){
275                 tcph->window=htons(30000);
276         }
277
278         /*Process DCCP Packet Types*/
279         switch(dccph->dccph_type){
280                 case DCCP_PKT_REQUEST:
281                         dbgprintf(2,"Packet Type: Request\n");
282                         if(!handle_request(new, old, h1, h2)){
283                                 return 0;
284                         }
285                         break;
286                 case DCCP_PKT_RESPONSE:
287                         dbgprintf(2,"Packet Type: Response\n");
288                         if(!handle_response(new,old,h1,h2)){
289                                 return 0;
290                         }
291                         break;
292                 case DCCP_PKT_DATA:
293                         if(!handle_data(new,old,h1,h2)){
294                                 return 0;
295                         }
296                         break;
297                 case DCCP_PKT_DATAACK:
298                         dbgprintf(2,"Packet Type: DataAck\n");
299                         if(!handle_dataack(new,old,h1,h2)){
300                                 return 0;
301                         }
302                         break;
303                 case DCCP_PKT_ACK:
304                         dbgprintf(2,"Packet Type: Ack\n");
305                         if(!handle_ack(new,old,h1,h2)){
306                                 return 0;
307                         }
308                         break;
309                 case DCCP_PKT_CLOSEREQ:
310                         dbgprintf(2,"Packet Type: CloseReq\n");
311                         if(!handle_closereq(new,old,h1,h2)){
312                                 return 0;
313                         }
314                         break;
315                 case DCCP_PKT_CLOSE:
316                         dbgprintf(2,"Packet Type: Close\n");
317                         if(!handle_close(new,old,h1,h2)){
318                                 return 0;
319                         }
320                         break;
321                 case DCCP_PKT_RESET:
322                         dbgprintf(2,"Packet Type: Reset\n");
323                         if(!handle_reset(new,old,h1,h2)){
324                                 return 0;
325                         }
326                         break;
327                 case DCCP_PKT_SYNC:
328                         dbgprintf(2,"Packet Type: Sync\n");
329                         if(!handle_sync(new,old,h1,h2)){
330                                 return 0;
331                         }
332                         break;
333                 case DCCP_PKT_SYNCACK:
334                         dbgprintf(2,"Packet Type: SyncAck\n");
335                         if(!handle_syncack(new,old,h1,h2)){
336                                 return 0;
337                         }
338                         break;
339                 default:
340                         dbgprintf(0,"Invalid DCCP Packet!!\n");
341                         return 0;
342                         break;
343         }
344
345         /*Compute TCP checksums*/
346         if(new->id_len==IP4_ADDR_LEN){
347                         tcph->check=0;
348                         tcph->check=ipv4_pseudohdr_chksum(new->data,
349                                         new->length, new->dest_id, new->src_id, 6);
350         }else if(new->id_len==IP6_ADDR_LEN){
351                         tcph->check=0;
352                         tcph->check=ipv6_pseudohdr_chksum(new->data,
353                                         new->length, new->dest_id, new->src_id, 6);
354         }else{
355                 tcph->check=0;
356                 dbgprintf(2,"Unknown ID Length, can't do checksums\n");
357         }
358
359         return 1;
360 }
361
362 int handle_request(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
363 {
364         struct tcphdr                           *tcph;
365         struct dccp_hdr                         *dccph;
366         struct dccp_hdr_ext             *dccphex;
367         int                                             datalength;
368         int                                                     optlen;
369         u_char*                                         tcpopt;
370         const u_char*                           dccpopt;
371
372         /*length check*/
373         if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext)+sizeof(struct dccp_hdr_request)){
374                 return 0;
375         }
376
377         /*cast header pointers*/
378         tcph=(struct tcphdr*)new->data;
379         dccph=(struct dccp_hdr*)old->data;
380         dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
381
382         /*determine data length*/
383         datalength=old->length - dccph->dccph_doff*4;
384
385         /*Process DCCP Options*/
386         dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext)+sizeof(struct dccp_hdr_request);
387         optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr)-sizeof(struct dccp_hdr_ext)-sizeof(struct dccp_hdr_request);
388         if(!parse_options(dccpopt,optlen,h1,h2)){
389                 return 0;
390         }
391
392         /*Do conversion*/
393         if(yellow){
394                 tcph->window=htons(0);
395         }
396         tcph->ack_seq=htonl(0);
397         if(h1->state==INIT){
398                 tcph->seq=htonl(initialize_hcon(h1, ntohl(dccphex->dccph_seq_low)));
399         }else{
400                 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),datalength, dccph->dccph_type));
401         }
402         tcph->syn=1;
403         tcph->ack=0;
404         tcph->fin=0;
405         tcph->rst=0;
406
407         /* add Sack-permitted option, if relevant*/
408         if(sack){
409                 tcpopt=(u_char*)(new->data + tcph->doff*4);
410                 *tcpopt=4;
411                 tcpopt++;
412                 *tcpopt=2;
413                 tcph->doff++;
414         }
415
416         /*calculate length*/
417         new->length=tcph->doff*4;
418         return 1;
419 }
420
421 int handle_response(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
422 {
423         struct tcphdr                           *tcph;
424         struct dccp_hdr                         *dccph;
425         struct dccp_hdr_ext             *dccphex;
426         struct dccp_hdr_ack_bits        *dccphack;
427         int                                                     optlen;
428         u_char*                                         tcpopt;
429         const u_char*                           dccpopt;
430
431         /*length check*/
432         if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext)
433                                         + sizeof(struct dccp_hdr_ack_bits)+sizeof(struct dccp_hdr_request)){
434                 return 0;
435         }
436
437         /*cast header pointers*/
438         tcph=(struct tcphdr*)new->data;
439         dccph=(struct dccp_hdr*)old->data;
440         dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
441         dccphack=(struct dccp_hdr_ack_bits*)(old->data+ sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
442
443         /*Process DCCP Options*/
444         dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) +
445                         sizeof(struct dccp_hdr_ack_bits) + sizeof(struct dccp_hdr_request);
446         optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext)
447                         - sizeof(struct dccp_hdr_ack_bits) - sizeof(struct dccp_hdr_request);
448         if(!parse_options(dccpopt,optlen,h1,h2)){
449                 return 0;
450         }
451
452         /*Do conversion*/
453         if(h2->state!=OPEN){
454                 dbgprintf(0,"Warning: DCCP Response without a Request!!\n");
455         }
456         tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
457         h1->high_ack=ntohl(tcph->ack_seq);
458         if(yellow){
459                 tcph->window=htons(0);
460         }
461         if(h1->state==INIT){
462                 tcph->seq=htonl(initialize_hcon(h1, ntohl(dccphex->dccph_seq_low)));
463         }
464         tcph->syn=1;
465         tcph->ack=1;
466         tcph->fin=0;
467         tcph->rst=0;
468
469         /* add Sack-permitted option, if relevant*/
470         if(sack){
471                 tcpopt=(u_char*)(new->data + tcph->doff*4);
472                 *tcpopt=4;
473                 *(tcpopt+1)=2;
474                 tcph->doff++;
475         }
476
477         /*calculate length*/
478         new->length=tcph->doff*4;
479         return 1;
480 }
481
482 int handle_dataack(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
483 {
484         struct tcphdr                           *tcph;
485         struct dccp_hdr                         *dccph;
486         struct dccp_hdr_ext             *dccphex;
487         struct dccp_hdr_ack_bits        *dccphack;
488         int                                             datalength;
489         int                                                     optlen;
490         const u_char*                           pd;
491         u_char*                                         npd;
492         const u_char*                           dccpopt;
493
494         /*length check*/
495         if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
496                 return 0;
497         }
498
499         /*cast header pointers*/
500         tcph=(struct tcphdr*)new->data;
501         dccph=(struct dccp_hdr*)old->data;
502         dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
503         dccphack=(struct dccp_hdr_ack_bits*)(old->data+ sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
504
505         /*determine data length*/
506         datalength=old->length - dccph->dccph_doff*4;
507         pd=old->data + dccph->dccph_doff*4;
508
509         /*Process DCCP Options*/
510         dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
511         optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
512         if(!parse_options(dccpopt,optlen,h1,h2)){
513                 return 0;
514         }
515
516         /*Do Conversion*/
517         if(green){
518                 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
519         }else{
520                 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
521         }
522         h1->high_ack=ntohl(tcph->ack_seq);
523         tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),datalength, dccph->dccph_type));
524         if(yellow){
525                 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
526         }
527         if(sack){
528                 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
529                         ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low),h1);
530                 }
531         }
532         tcph->syn=0;
533         tcph->ack=1;
534         tcph->fin=0;
535         tcph->rst=0;
536
537         /*copy data*/
538         npd=new->data + tcph->doff*4;
539         memcpy(npd, pd, datalength);
540
541         /*calculate length*/
542         new->length=tcph->doff*4 + datalength;
543         return 1;
544 }
545
546 int handle_ack(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
547 {
548         struct tcphdr                           *tcph;
549         struct dccp_hdr                         *dccph;
550         struct dccp_hdr_ext             *dccphex;
551         struct dccp_hdr_ack_bits        *dccphack;
552         int                                                     optlen;
553         const u_char*                           dccpopt;
554
555         /*length check*/
556         if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
557                 return 0;
558         }
559
560         /*cast header pointers*/
561         tcph=(struct tcphdr*)new->data;
562         dccph=(struct dccp_hdr*)old->data;
563         dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
564         dccphack=(struct dccp_hdr_ack_bits*)(old->data+ sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
565
566         /*Process DCCP Options*/
567         dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
568         optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
569         if(!parse_options(dccpopt,optlen,h1,h2)){
570                 return 0;
571         }
572
573         /*Do Conversion*/
574         if(green){
575                 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
576         }else{
577                 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
578         }
579         h1->high_ack=ntohl(tcph->ack_seq);
580         tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
581         if(yellow){
582                 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*1400);
583                 if(-interp_ack_vect((u_char*)dccph)*1400 > 65535){
584                         dbgprintf(0,"Note: TCP Window Overflow @ %d.%d\n", (int)old->h->ts.tv_sec, (int)old->h->ts.tv_usec);
585                 }
586         }
587         if(sack){
588                 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
589                         ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low),h1);
590                 }
591         }
592
593         tcph->syn=0;
594         tcph->ack=1;
595         tcph->fin=0;
596         tcph->rst=0;
597
598         /*calculate length*/
599         new->length=tcph->doff*4 + 1;
600         return 1;
601 }
602
603 int handle_closereq(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
604 {
605         struct tcphdr                           *tcph;
606         struct dccp_hdr                         *dccph;
607         struct dccp_hdr_ext             *dccphex;
608         struct dccp_hdr_ack_bits        *dccphack;
609         int                                                     optlen;
610         const u_char*                           dccpopt;
611
612         /*length check*/
613         if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
614                 return 0;
615         }
616
617         /*cast header pointers*/
618         tcph=(struct tcphdr*)new->data;
619         dccph=(struct dccp_hdr*)old->data;
620         dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
621         dccphack=(struct dccp_hdr_ack_bits*)(old->data+ sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
622
623         /*Process DCCP Options*/
624         dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
625         optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
626         if(!parse_options(dccpopt,optlen,h1,h2)){
627                 return 0;
628         }
629
630         /*Do Conversion*/
631         if(green){
632                 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
633         }else{
634                 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
635         }
636         h1->high_ack=ntohl(tcph->ack_seq);
637         tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
638         if(yellow){
639                 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
640         }
641         if(sack){
642                 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
643                         ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low),h1);
644                 }
645         }
646
647         tcph->syn=0;
648         tcph->ack=1;
649         tcph->fin=1;
650         tcph->rst=0;
651
652         /*calculate length*/
653         new->length=tcph->doff*4;
654         return 1;
655 }
656
657 int handle_close(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
658 {
659         struct tcphdr                           *tcph;
660         struct dccp_hdr                         *dccph;
661         struct dccp_hdr_ext             *dccphex;
662         struct dccp_hdr_ack_bits        *dccphack;
663         int                                                     optlen;
664         const u_char*                           dccpopt;
665
666         /*length check*/
667         if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
668                 return 0;
669         }
670
671         /*cast header pointers*/
672         tcph=(struct tcphdr*)new->data;
673         dccph=(struct dccp_hdr*)old->data;
674         dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
675         dccphack=(struct dccp_hdr_ack_bits*)(old->data+ sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
676
677         /*Process DCCP Options*/
678         dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
679         optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
680         if(!parse_options(dccpopt,optlen,h1,h2)){
681                 return 0;
682         }
683
684         /*Do Conversion*/
685         update_state(h1,CLOSE);
686         if(green){
687                 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
688         }else{
689                 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
690         }
691         h1->high_ack=ntohl(tcph->ack_seq);
692         tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
693         if(yellow){
694                 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
695         }
696         if(sack){
697                 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
698                         ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low),h1);
699                 }
700         }
701
702         tcph->syn=0;
703         tcph->ack=1;
704         tcph->fin=1;
705         tcph->rst=0;
706
707         /*calculate length*/
708         new->length=tcph->doff*4;
709         return 1;
710 }
711
712 int handle_reset(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
713 {
714         struct tcphdr                           *tcph;
715         struct dccp_hdr                         *dccph;
716         struct dccp_hdr_ext             *dccphex;
717         struct dccp_hdr_ack_bits        *dccphack;
718         int                                                     optlen;
719         const u_char*                           dccpopt;
720
721         /*length check*/
722         if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
723                 return 0;
724         }
725
726         /*cast header pointers*/
727         tcph=(struct tcphdr*)new->data;
728         dccph=(struct dccp_hdr*)old->data;
729         dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
730         dccphack=(struct dccp_hdr_ack_bits*)(old->data+ sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
731
732         /*Process DCCP Options*/
733         dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
734         optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
735         if(!parse_options(dccpopt,optlen,h1,h2)){
736                 return 0;
737         }
738
739         /*Do Conversion*/
740         if(h2->state==CLOSE){
741                 update_state(h1,CLOSE);
742         }
743         if(green){
744                 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
745         }else{
746                 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
747         }
748         h1->high_ack=ntohl(tcph->ack_seq);
749         tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
750         if(yellow){
751                 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
752         }
753         if(sack){
754                 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
755                         ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low),h1);
756                 }
757         }
758
759         tcph->syn=0;
760         tcph->ack=1;
761         tcph->fin=1;
762         tcph->rst=0;
763
764         /*calculate length*/
765         new->length=tcph->doff*4;
766         return 1;
767 }
768
769 int handle_sync(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
770 {
771         struct tcphdr                           *tcph;
772         struct dccp_hdr                         *dccph;
773         struct dccp_hdr_ext             *dccphex;
774         struct dccp_hdr_ack_bits        *dccphack;
775         int                                                     optlen;
776         const u_char*                           dccpopt;
777
778         /*length check*/
779         if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
780                 return 0;
781         }
782
783         /*cast header pointers*/
784         tcph=(struct tcphdr*)new->data;
785         dccph=(struct dccp_hdr*)old->data;
786         dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
787         dccphack=(struct dccp_hdr_ack_bits*)(old->data+ sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
788
789         /*Process DCCP Options*/
790         dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
791         optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
792         if(!parse_options(dccpopt,optlen,h1,h2)){
793                 return 0;
794         }
795
796         /*Do Conversion*/
797         if(green){
798                 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
799         }else{
800                 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
801         }
802         h1->high_ack=ntohl(tcph->ack_seq);
803         tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),0,dccph->dccph_type));
804         if(yellow){
805                 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
806         }else{
807                 tcph->window=htons(0);
808         }
809         if(sack){
810                 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
811                         ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low),h1);
812                 }
813         }
814
815         tcph->syn=0;
816         tcph->ack=1;
817         tcph->fin=0;
818         tcph->rst=0;
819
820         /*calculate length*/
821         new->length=tcph->doff*4;
822         return 1;
823 }
824
825 int handle_syncack(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
826 {
827         struct tcphdr                           *tcph;
828         struct dccp_hdr                         *dccph;
829         struct dccp_hdr_ext             *dccphex;
830         struct dccp_hdr_ack_bits        *dccphack;
831         int                                                     optlen;
832         const u_char*                           dccpopt;
833
834         /*length check*/
835         if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
836                 return 0;
837         }
838
839         /*cast header pointers*/
840         tcph=(struct tcphdr*)new->data;
841         dccph=(struct dccp_hdr*)old->data;
842         dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
843         dccphack=(struct dccp_hdr_ack_bits*)(old->data+ sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
844
845         /*Process DCCP Options*/
846         dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
847         optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
848         if(!parse_options(dccpopt,optlen,h1,h2)){
849                 return 0;
850         }
851
852         /*Do Conversion*/
853         if(green){
854                 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
855         }else{
856                 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
857         }
858         h1->high_ack=ntohl(tcph->ack_seq);
859         tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),0,dccph->dccph_type));
860         if(yellow){
861                 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
862         }else{
863                 tcph->window=htons(0);
864         }
865         if(sack){
866                 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
867                         ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low),h1);
868                 }
869         }
870
871         tcph->syn=0;
872         tcph->ack=1;
873         tcph->fin=0;
874         tcph->rst=0;
875
876         /*calculate length*/
877         new->length=tcph->doff*4;
878         return 1;
879 }
880
881 int handle_data(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
882 {
883         struct tcphdr                           *tcph;
884         struct dccp_hdr                         *dccph;
885         struct dccp_hdr_ext             *dccphex;
886         int                                             datalength;
887         int                                                     optlen;
888         const u_char*                           pd;
889         u_char*                                         npd;
890         const u_char*                           dccpopt;
891
892         /*length check*/
893         if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext)){
894                 return 0;
895         }
896
897         /*cast header pointers*/
898         tcph=(struct tcphdr*)new->data;
899         dccph=(struct dccp_hdr*)old->data;
900         dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
901
902         /*determine data length*/
903         datalength=old->length - dccph->dccph_doff*4;
904         pd=old->data + dccph->dccph_doff*4;
905
906         /*Process DCCP Options*/
907         dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext);
908         optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext);
909         if(!parse_options(dccpopt,optlen,h1,h2)){
910                 return 0;
911         }
912
913         /*Do conversion*/
914         tcph->ack_seq=htonl(h1->high_ack);
915         tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),datalength, dccph->dccph_type));
916         tcph->syn=0;
917         tcph->ack=1;
918         tcph->fin=0;
919         tcph->rst=0;
920
921         /*copy data*/
922         npd=new->data + tcph->doff*4;
923         memcpy(npd, pd, datalength);
924
925         /*calculate length*/
926         new->length=tcph->doff*4 + datalength;
927         return 1;
928 }
929
930 int parse_options(const u_char* opt_start, int len, struct hcon* A, struct hcon* B)
931 {
932         int optlen;
933         int length;
934         const u_char* opt;
935
936         /*setup pointer to DCCP options and determine how long the options are*/
937         optlen=len;
938         opt=opt_start;
939
940         /*parse options*/
941         while(optlen > 0){
942                 /*One byte options (no length)*/
943                 if(*opt< 32){
944                         optlen--;
945                         opt++;
946                         continue;
947                 }
948
949                 /*Check option length*/
950                 length=*(opt+1);
951                 if(length > optlen){
952                         dbgprintf(0, "Warning: Option would extend into packet data\n");
953                         return 0;
954                 }
955                 if(length < 2){
956                         dbgprintf(0, "Warning: Bad Option!\n");
957                         return 0;
958                 }
959
960                 /*Ack Vector Option*/
961                 if(*opt==38 || *opt==39){
962                         if(B->type==UNKNOWN){
963                                 B->type=CCID2;
964                                 dbgprintf(1,"Half-connection from port %i to %i probably using CCID 2\n",
965                                                                                         ntohs(B->port),ntohs(A->port));
966                         }
967                 }
968
969                 /*NDP Count Option*/
970                 if(*opt==37){
971                         if(B->type==UNKNOWN){
972                                 B->type=CCID3;
973                                 dbgprintf(1,"Half-connection from port %i to %i probably using CCID 3\n",
974                                                                                         ntohs(B->port),ntohs(A->port));
975                         }
976                 }
977
978                 /*Feature negotation*/
979                 if(*opt==32){
980                         /*Change L*/
981                         if(!process_feature(opt+2,length-2,FALSE,TRUE,A,B)){
982                                 return 0;
983                         }
984                 }
985                 if(*opt==33){
986                         /*Confirm L*/
987                         if(!process_feature(opt+2,length-2,TRUE,TRUE,A,B)){
988                                 return 0;
989                         }
990                 }
991                 if(*opt==34){
992                         /*Change R*/
993                         if(!process_feature(opt+2,length-2,FALSE,FALSE,A,B)){
994                                 return 0;
995                         }
996                 }
997                 if(*opt==35){
998                         /*Confirm R*/
999                         if(!process_feature(opt+2,length-2,TRUE,FALSE,A,B)){
1000                                 return 0;
1001                         }
1002                 }
1003
1004                 optlen-=length;
1005                 opt+=length;
1006         }
1007
1008         return 1;
1009 }
1010
1011 int process_feature(const u_char* feat, int len, int confirm, int L, struct hcon* A, struct hcon* B)
1012 {
1013         const u_char* val;
1014         int ccid;
1015
1016         val=feat+1;
1017
1018         switch(*feat){
1019                 case 1:
1020                         /*CCID*/
1021                         if(confirm==TRUE){
1022                                 switch(*val){
1023                                         case 2:
1024                                                 ccid=CCID2;
1025                                                 break;
1026                                         case 3:
1027                                                 ccid=CCID3;
1028                                                 break;
1029                                         default:
1030                                                 ccid=UNKNOWN;
1031                                                 break;
1032                                 }
1033                                 if(L==TRUE){
1034                                         B->type=ccid;
1035                                         dbgprintf(1,"Half-connection from port %i to %i using CCID %i\n",
1036                                                         ntohs(B->port),ntohs(A->port), *val);
1037                                 }else{
1038                                         A->type=ccid;
1039                                         dbgprintf(1,"Half-connection from port %i to %i using CCID %i\n",
1040                                                         ntohs(A->port),ntohs(B->port), *val);
1041                                 }
1042                         }
1043                         break;
1044                 case 2:
1045                         /*Short sequence nums*/
1046                         if(confirm==TRUE && *val==1){
1047                                 B->type=IGNORE;
1048                                 A->type=IGNORE;
1049                                 dbgprintf(0,"Error: DCCP is trying to turn on short sequence numbers\n"
1050                                                 "  for the connection between %i and %i. We do not support this.\n"
1051                                                 "  This connection will be ignored.",ntohs(A->port),ntohs(B->port));
1052                                 return 0;
1053                         }
1054                         break;
1055         }
1056         return 1;
1057 }
1058
1059 /*Ack Vector to SACK Option*/
1060 void ack_vect2sack(struct hcon *hcn, struct tcphdr *tcph, u_char* tcpopts, u_char* dccphdr,
1061                                                                                                                                 d_seq_num dccpack, struct hcon* o_hcn)
1062 {
1063         int hdrlen=((struct dccp_hdr*)dccphdr)->dccph_doff*4;
1064         int optlen;
1065         int len;
1066         int tmp;
1067         d_seq_num bp;
1068         u_char* temp;
1069         u_char* opt;
1070         u_char* cur;
1071         u_char* tlen;
1072         u_int32_t bL=0;
1073         u_int32_t bR;
1074         u_int32_t* pL;
1075         u_int32_t* pR;
1076         int num_blocks;
1077         int cont;
1078         int isopt;
1079
1080         /*setup pointer to DCCP options and determine how long the options are*/
1081         optlen=hdrlen-sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
1082         opt=dccphdr + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
1083
1084         if(optlen<=0){
1085                 return;
1086         }
1087
1088         /*setup tcp pointers*/
1089         num_blocks=4;
1090         *tcpopts=5;
1091         tlen=tcpopts+1;
1092         temp=tlen;
1093         temp++;
1094         pL=(u_int32_t*)temp;
1095         pR=pL+1;
1096
1097         /*setup tcp control variables*/
1098         bp=dccpack;
1099         cont=0;
1100         *tlen=2;
1101         isopt=0;
1102
1103         /*parse options*/
1104         while(optlen > 0){
1105
1106                 /*One byte options (no length)*/
1107                 if(*opt< 32){
1108                         optlen--;
1109                         opt++;
1110                         continue;
1111                 }
1112
1113                 len=*(opt+1);
1114                 if(len > optlen){
1115                         dbgprintf(0, "Warning: Option would extend into packet data\n");
1116                         break;
1117                 }
1118
1119                 /*Ack Vector Option*/
1120                 if(*opt==38 || *opt==39){
1121                         tmp=len-2;
1122                         cur=opt+2;
1123                         /*loop through Vector*/
1124                         while(tmp > 0){
1125                                 /*ack vector works BACKWARDS through time*/
1126
1127                                 if((*cur & 0xC0)==0xC0 || (*cur & 0xC0)==0x40){ //lost packet
1128                                         if(cont){ /*end a SACK run, if one is started*/
1129                                                 bR=convert_ack(hcn, bp,o_hcn);
1130                                                 cont=0;
1131                                                 num_blocks--;
1132                                                 *pR=htonl(bR);
1133                                                 *pL=htonl(bL);
1134                                                 tcph->doff+=2;
1135                                                 *tlen+=8;
1136                                                 pL=pR+1;
1137                                                 pR=pL+1;
1138                                         }
1139                                         bp= bp - (*cur & 0x3F)- 1;
1140                                 }
1141
1142                                 if((*cur & 0xC0)==0x00){ //received packet
1143                                         if(!cont){ /*if no SACK run and we can start another one, do so*/
1144                                                 if(num_blocks>0){
1145                                                         bL=convert_ack(hcn, bp, o_hcn);
1146                                                         isopt=1;
1147                                                         cont=1;
1148
1149                                                 }
1150                                         }
1151                                         bp =  bp -(*cur & 0x3F)- 1;
1152                                 }
1153                                 tmp--;
1154                                 cur++;
1155                         }
1156                 }
1157
1158                 optlen-=len;
1159                 opt+=len;
1160         }
1161
1162         /*if we are in the middle of a SACK run, close it*/
1163         if(cont){
1164                 bR=convert_ack(hcn, bp,o_hcn);
1165                 *pR=htonl(bR);
1166                 *pL=htonl(bL);
1167                 tcph->doff+=2;
1168                 *tlen+=8;
1169                 cont=0;
1170         }
1171
1172         /*adjust length if the option is actually added*/
1173         if(isopt){
1174                 tcph->doff+=1;
1175         }
1176 return;
1177 }
1178
1179 void version()
1180 {
1181         dbgprintf(0, "dccp2tcp version %.1f\n",DCCP2TCP_VERSION);
1182         dbgprintf(0, "Copyright (C) %i Samuel Jero <sj323707@ohio.edu>\n",COPYRIGHT_YEAR);
1183         dbgprintf(0, "This program comes with ABSOLUTELY NO WARRANTY.\n");
1184         dbgprintf(0, "This is free software, and you are welcome to\n");
1185         dbgprintf(0, "redistribute it under certain conditions.\n");
1186         exit(0);
1187 }
1188
1189 /*Usage information for program*/
1190 void usage()
1191 {
1192         dbgprintf(0,"Usage: dccp2tcp [-d] [-h] [-V] [-y] [-g] [-s] dccp_file tcp_file\n");
1193         dbgprintf(0, "          -d   Debug. May be repeated for aditional verbosity.\n");
1194         dbgprintf(0, "          -V   Version information\n");
1195         dbgprintf(0, "          -h   Help\n");
1196         dbgprintf(0, "          -y   Yellow line is highest ACK\n");
1197         dbgprintf(0, "          -g   Green line is highest ACK\n");
1198         dbgprintf(0, "          -s   convert ACK Vectors to SACKS\n");
1199         exit(0);
1200 }
1201
1202 /*Debug Printf*/
1203 void dbgprintf(int level, const char *fmt, ...)
1204 {
1205     va_list args;
1206     if(debug>=level){
1207         va_start(args, fmt);
1208         vfprintf(stderr, fmt, args);
1209         va_end(args);
1210     }
1211 }