1 /******************************************************************************
2 Utility to convert a DCCP flow to a TCP flow for DCCP analysis via
5 Copyright (C) 2013 Samuel Jero <sj323707@ohio.edu>
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.
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.
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/>.
20 Author: Samuel Jero <sj323707@ohio.edu>
24 1)DCCP MUST use 48 bit sequence numbers
25 2)DCCP Ack packets show up as TCP packets containing one byte
26 ******************************************************************************/
30 #define DCCP2TCP_VERSION 1.6
31 #define COPYRIGHT_YEAR 2013
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*/
40 pcap_t* in; /*libpcap input file discriptor*/
41 pcap_dumper_t *out; /*libpcap output file discriptor*/
42 struct connection *chead; /*connection list*/
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);
66 /*Parse commandline options and open files*/
67 int main(int argc, char *argv[])
74 /*parse commandline options*/
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*/
87 tfile=argv[i]; /*assign second non-dash argument to the dccp file*/
93 if(argv[i][1]=='d' && strlen(argv[i])==2){ /* -d */
96 if(argv[i][1]=='y' && strlen(argv[i])==2){ /* -y */
99 if(argv[i][1]=='g' && strlen(argv[i])==2){ /* -g */
102 if(argv[i][1]=='s' && strlen(argv[i])==2){ /* -s */
105 if(argv[i][1]=='h' && strlen(argv[i])==2){ /* -h */
108 if(argv[i][1]=='V' && strlen(argv[i])==2){ /* -V */
114 if(dfile==NULL || tfile==NULL){
118 /*all options validated*/
121 dbgprintf(1,"Debug On\n");
123 dbgprintf(1,"Tcptrace green line at highest acknowledgment\n");
125 dbgprintf(1,"Tcptrace green line at highest acknowledged acknowledgment\n");
128 dbgprintf(1,"Tcptrace yellow line at highest acknowledgment\n");
130 dbgprintf(1,"Tcptrace yellow line window value (a made up number)\n");
133 dbgprintf(1,"Adding TCP SACKS\n");
135 dbgprintf(1,"Input file: %s\n", dfile);
136 dbgprintf(1,"Output file: %s\n", tfile);
139 /*attempt to open input file*/
140 in=pcap_open_offline(dfile, erbuffer);
142 dbgprintf(0,"Error opening input file\n");
146 /*attempt to open output file*/
147 out=pcap_dump_open(in,tfile);
149 dbgprintf(0,"Error opening output file\n");
155 u_char *user=(u_char*)out;
156 pcap_loop(in, -1, handle_packet, user);
160 pcap_dump_close(out);
162 /*Delete all connections*/
163 cleanup_connections();
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)
172 struct pcap_pkthdr nh;
175 struct const_packet old;
177 /*Determine the link type for this packet*/
178 link_type=pcap_datalink(in);
180 /*create new libpcap header*/
181 memcpy(&nh, h, sizeof(struct pcap_pkthdr));
183 /*Setup packet structs*/
185 old.length=h->caplen;
190 new.length=MAX_PACKET;
194 /*create buffer for new packet*/
195 new.data=ndata=malloc(MAX_PACKET);
197 dbgprintf(0,"Error: Couldn't allocate Memory\n");
201 /*make sure the packet is all zero*/
202 memset(new.data, 0, MAX_PACKET);
204 /*do all the fancy conversions*/
205 if(!do_encap(link_type, &new, &old)){
211 pcap_dump(user,&nh, ndata);
217 /*do all the dccp to tcp conversions*/
218 int convert_packet(struct packet *new, const struct const_packet* old)
221 struct dccp_hdr *dccph;
222 struct dccp_hdr_ext *dccphex;
223 struct hcon *h1=NULL;
224 struct hcon *h2=NULL;
229 if(!new || !old || !new->data || !old->data || !new->h || !old->h){
230 dbgprintf(0,"Error: Convert Packet Function given bad data!\n");
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");
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));
245 dbgprintf(2,"Sequence Number: %llu\n", (unsigned long long)
246 (((unsigned long)ntohs(dccph->dccph_seq)<<32) + ntohl(dccphex->dccph_seq_low)));
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");
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");
260 if(h1==NULL || h2==NULL){
261 dbgprintf(0, "Error: Can't Get Hosts!\n");
264 if(h1->state==IGNORE || h2->state==IGNORE){
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));
270 dbgprintf(2,"Ignoring packet between %i and %i\n",
271 ntohs(dccph->dccph_sport), ntohs(dccph->dccph_dport));
276 /*set TCP standard features*/
277 tcph->source=dccph->dccph_sport;
278 tcph->dest=dccph->dccph_dport;
280 tcph->check=htonl(0);
283 /*Adjust TCP advertised window size*/
285 tcph->window=htons(30000);
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)){
296 case DCCP_PKT_RESPONSE:
297 dbgprintf(2,"Packet Type: Response\n");
298 if(!handle_response(new,old,h1,h2)){
303 if(!handle_data(new,old,h1,h2)){
307 case DCCP_PKT_DATAACK:
308 dbgprintf(2,"Packet Type: DataAck\n");
309 if(!handle_dataack(new,old,h1,h2)){
314 dbgprintf(2,"Packet Type: Ack\n");
315 if(!handle_ack(new,old,h1,h2)){
319 case DCCP_PKT_CLOSEREQ:
320 dbgprintf(2,"Packet Type: CloseReq\n");
321 if(!handle_closereq(new,old,h1,h2)){
326 dbgprintf(2,"Packet Type: Close\n");
327 if(!handle_close(new,old,h1,h2)){
332 dbgprintf(2,"Packet Type: Reset\n");
333 if(!handle_reset(new,old,h1,h2)){
338 dbgprintf(2,"Packet Type: Sync\n");
339 if(!handle_sync(new,old,h1,h2)){
343 case DCCP_PKT_SYNCACK:
344 dbgprintf(2,"Packet Type: SyncAck\n");
345 if(!handle_syncack(new,old,h1,h2)){
350 dbgprintf(0,"Invalid DCCP Packet!!\n");
355 /*Compute TCP checksums*/
356 if(new->id_len==IP4_ADDR_LEN){
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){
362 tcph->check=ipv6_pseudohdr_chksum(new->data,
363 new->length, new->dest_id, new->src_id, 6);
366 dbgprintf(2,"Unknown ID Length, can't do checksums\n");
372 int handle_request(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
375 struct dccp_hdr *dccph;
376 struct dccp_hdr_ext *dccphex;
380 const u_char* dccpopt;
383 if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext)+sizeof(struct dccp_hdr_request)){
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));
392 /*determine data length*/
393 datalength=old->length - dccph->dccph_doff*4;
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)){
404 tcph->window=htons(0);
406 tcph->ack_seq=htonl(0);
408 tcph->seq=htonl(initialize_hcon(h1, ntohl(dccphex->dccph_seq_low)));
410 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),datalength, dccph->dccph_type));
417 /* add Sack-permitted option, if relevant*/
419 tcpopt=(u_char*)(new->data + tcph->doff*4);
427 new->length=tcph->doff*4;
431 int handle_response(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
434 struct dccp_hdr *dccph;
435 struct dccp_hdr_ext *dccphex;
436 struct dccp_hdr_ack_bits *dccphack;
439 const u_char* dccpopt;
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)){
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));
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)){
464 dbgprintf(0,"Warning: DCCP Response without a Request!!\n");
466 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
467 h1->high_ack=ntohl(tcph->ack_seq);
469 tcph->window=htons(0);
472 tcph->seq=htonl(initialize_hcon(h1, ntohl(dccphex->dccph_seq_low)));
479 /* add Sack-permitted option, if relevant*/
481 tcpopt=(u_char*)(new->data + tcph->doff*4);
488 new->length=tcph->doff*4;
492 int handle_dataack(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
495 struct dccp_hdr *dccph;
496 struct dccp_hdr_ext *dccphex;
497 struct dccp_hdr_ack_bits *dccphack;
502 const u_char* dccpopt;
505 if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
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));
515 /*determine data length*/
516 datalength=old->length - dccph->dccph_doff*4;
517 pd=old->data + dccph->dccph_doff*4;
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)){
528 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
530 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
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));
535 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
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);
548 npd=new->data + tcph->doff*4;
549 memcpy(npd, pd, datalength);
552 new->length=tcph->doff*4 + datalength;
556 int handle_ack(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
559 struct dccp_hdr *dccph;
560 struct dccp_hdr_ext *dccphex;
561 struct dccp_hdr_ack_bits *dccphack;
563 const u_char* dccpopt;
566 if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
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));
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)){
585 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
587 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
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));
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);
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);
609 new->length=tcph->doff*4 + 1;
613 int handle_closereq(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
616 struct dccp_hdr *dccph;
617 struct dccp_hdr_ext *dccphex;
618 struct dccp_hdr_ack_bits *dccphack;
620 const u_char* dccpopt;
623 if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
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));
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)){
642 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
644 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
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));
649 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
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);
663 new->length=tcph->doff*4;
667 int handle_close(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
670 struct dccp_hdr *dccph;
671 struct dccp_hdr_ext *dccphex;
672 struct dccp_hdr_ack_bits *dccphack;
674 const u_char* dccpopt;
677 if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
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));
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)){
695 update_state(h1,CLOSE);
697 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
699 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
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));
704 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
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);
718 new->length=tcph->doff*4;
722 int handle_reset(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
725 struct dccp_hdr *dccph;
726 struct dccp_hdr_ext *dccphex;
727 struct dccp_hdr_ack_bits *dccphack;
729 const u_char* dccpopt;
732 if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
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));
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)){
750 if(h2->state==CLOSE){
751 update_state(h1,CLOSE);
754 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
756 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
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));
761 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
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);
775 new->length=tcph->doff*4;
779 int handle_sync(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
782 struct dccp_hdr *dccph;
783 struct dccp_hdr_ext *dccphex;
784 struct dccp_hdr_ack_bits *dccphack;
786 const u_char* dccpopt;
789 if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
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));
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)){
808 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
810 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
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));
815 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
817 tcph->window=htons(0);
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);
831 new->length=tcph->doff*4;
835 int handle_syncack(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
838 struct dccp_hdr *dccph;
839 struct dccp_hdr_ext *dccphex;
840 struct dccp_hdr_ack_bits *dccphack;
842 const u_char* dccpopt;
845 if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
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));
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)){
864 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
866 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
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));
871 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
873 tcph->window=htons(0);
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);
887 new->length=tcph->doff*4;
891 int handle_data(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
894 struct dccp_hdr *dccph;
895 struct dccp_hdr_ext *dccphex;
900 const u_char* dccpopt;
903 if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext)){
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));
912 /*determine data length*/
913 datalength=old->length - dccph->dccph_doff*4;
914 pd=old->data + dccph->dccph_doff*4;
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)){
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));
932 npd=new->data + tcph->doff*4;
933 memcpy(npd, pd, datalength);
936 new->length=tcph->doff*4 + datalength;
940 int parse_options(const u_char* opt_start, int len, const struct const_packet* pkt,
941 struct hcon* A, struct hcon* B)
949 /*setup pointer to DCCP options and determine how long the options are*/
955 /*One byte options (no length)*/
962 /*Check option length*/
965 dbgprintf(0, "Warning: Option would extend into packet data\n");
969 dbgprintf(0, "Warning: Bad Option!\n");
973 /*Ack Vector Option*/
974 if(*opt==38 || *opt==39){
975 if(B->type==UNKNOWN){
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));
982 dbgprintf(1,"Half-connection from port %i to %i probably using CCID 2\n",
983 ntohs(B->port),ntohs(A->port));
990 if(B->type==UNKNOWN){
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));
997 dbgprintf(1,"Half-connection from port %i to %i probably using CCID 3\n",
998 ntohs(B->port),ntohs(A->port));
1003 /*Feature negotation*/
1006 if(!process_feature(opt+2,length-2,FALSE,TRUE,pkt,A,B)){
1012 if(!process_feature(opt+2,length-2,TRUE,TRUE,pkt,A,B)){
1018 if(!process_feature(opt+2,length-2,FALSE,FALSE,pkt,A,B)){
1024 if(!process_feature(opt+2,length-2,TRUE,FALSE,pkt,A,B)){
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)
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);
1068 dbgprintf(1,"Half-connection from port %i to %i using CCID %i\n",
1069 ntohs(B->port),ntohs(A->port), *val);
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);
1078 dbgprintf(1,"Half-connection from port %i to %i using CCID %i\n",
1079 ntohs(A->port),ntohs(B->port), *val);
1085 /*Short sequence nums*/
1086 if(confirm==TRUE && *val==1){
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));
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)
1103 int hdrlen=((struct dccp_hdr*)dccphdr)->dccph_doff*4;
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);
1128 /*setup tcp pointers*/
1134 pL=(u_int32_t*)temp;
1137 /*setup tcp control variables*/
1146 /*One byte options (no length)*/
1155 dbgprintf(0, "Warning: Option would extend into packet data\n");
1159 /*Ack Vector Option*/
1160 if(*opt==38 || *opt==39){
1163 /*loop through Vector*/
1165 /*ack vector works BACKWARDS through time*/
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);
1179 bp= bp - (*cur & 0x3F)- 1;
1182 if((*cur & 0xC0)==0x00){ //received packet
1183 if(!cont){ /*if no SACK run and we can start another one, do so*/
1185 bL=convert_ack(hcn, bp, o_hcn);
1191 bp = bp -(*cur & 0x3F)- 1;
1202 /*if we are in the middle of a SACK run, close it*/
1204 bR=convert_ack(hcn, bp,o_hcn);
1212 /*adjust length if the option is actually added*/
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");
1229 /*Usage information for program*/
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");
1243 void dbgprintf(int level, const char *fmt, ...)
1247 va_start(args, fmt);
1248 vfprintf(stderr, fmt, args);