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