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