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