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]=='v' && strlen(argv[i])==2){ /* -v */
95 }else if(argv[i][1]=='y' && strlen(argv[i])==2){ /* -y */
97 }else if(argv[i][1]=='g' && strlen(argv[i])==2){ /* -g */
99 }else if(argv[i][1]=='s' && strlen(argv[i])==2){ /* -s */
101 }else if(argv[i][1]=='h' && strlen(argv[i])==2){ /* -h */
103 }else if(argv[i][1]=='V' && strlen(argv[i])==2){ /* -V */
111 if(dfile==NULL || tfile==NULL){
115 /*all options validated*/
119 dbgprintf(1,"Tcptrace green line at highest acknowledgment\n");
121 dbgprintf(1,"Tcptrace green line at highest acknowledged acknowledgment\n");
124 dbgprintf(1,"Tcptrace yellow line at highest acknowledgment\n");
126 dbgprintf(1,"Tcptrace yellow line window value (a made up number)\n");
129 dbgprintf(1,"Adding TCP SACKS\n");
131 dbgprintf(1,"Input file: %s\n", dfile);
132 dbgprintf(1,"Output file: %s\n", tfile);
135 /*attempt to open input file*/
136 in=pcap_open_offline(dfile, erbuffer);
138 dbgprintf(0,"Error opening input file\n");
142 /*attempt to open output file*/
143 out=pcap_dump_open(in,tfile);
145 dbgprintf(0,"Error opening output file\n");
151 u_char *user=(u_char*)out;
152 pcap_loop(in, -1, handle_packet, user);
156 pcap_dump_close(out);
158 /*Delete all connections*/
159 cleanup_connections();
164 /*call back function for pcap_loop--do basic packet handling*/
165 void handle_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
168 struct pcap_pkthdr nh;
171 struct const_packet old;
173 /*Determine the link type for this packet*/
174 link_type=pcap_datalink(in);
176 /*create new libpcap header*/
177 memcpy(&nh, h, sizeof(struct pcap_pkthdr));
179 /*Setup packet structs*/
181 old.length=h->caplen;
186 new.length=MAX_PACKET;
190 /*create buffer for new packet*/
191 new.data=ndata=malloc(MAX_PACKET);
193 dbgprintf(0,"Error: Couldn't allocate Memory\n");
197 /*make sure the packet is all zero*/
198 memset(new.data, 0, MAX_PACKET);
200 /*do all the fancy conversions*/
201 if(!do_encap(link_type, &new, &old)){
207 pcap_dump(user,&nh, ndata);
213 /*do all the dccp to tcp conversions*/
214 int convert_packet(struct packet *new, const struct const_packet* old)
217 struct dccp_hdr *dccph;
218 struct dccp_hdr_ext *dccphex;
219 struct hcon *h1=NULL;
220 struct hcon *h2=NULL;
225 if(!new || !old || !new->data || !old->data || !new->h || !old->h){
226 dbgprintf(0,"Error: Convert Packet Function given bad data!\n");
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");
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));
241 dbgprintf(2,"Sequence Number: %llu\n", (unsigned long long)
242 (((unsigned long)ntohs(dccph->dccph_seq)<<32) + ntohl(dccphex->dccph_seq_low)));
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");
251 if(get_host(new->src_id, new->dest_id, new->id_len, dccph->dccph_sport,
252 dccph->dccph_dport, dccph->dccph_type,&h1, &h2)){
253 dbgprintf(0,"Error: Can't Get Hosts!\n");
256 if(h1==NULL || h2==NULL){
257 dbgprintf(0, "Error: Can't Get Hosts!\n");
260 if(h1->state==IGNORE || h2->state==IGNORE){
262 dbgprintf(2,"Ignoring packet between %s:%i and %s:%i\n",
263 old->print_id(buf1,100,old->src_id,old->id_len),ntohs(dccph->dccph_sport),
264 old->print_id(buf2,100,old->dest_id,old->id_len), ntohs(dccph->dccph_dport));
266 dbgprintf(2,"Ignoring packet between %i and %i\n",
267 ntohs(dccph->dccph_sport), ntohs(dccph->dccph_dport));
272 /*set TCP standard features*/
273 tcph->source=dccph->dccph_sport;
274 tcph->dest=dccph->dccph_dport;
276 tcph->check=htonl(0);
279 /*Adjust TCP advertised window size*/
281 tcph->window=htons(30000);
284 /*Process DCCP Packet Types*/
285 switch(dccph->dccph_type){
286 case DCCP_PKT_REQUEST:
287 dbgprintf(2,"Packet Type: Request\n");
288 if(!handle_request(new, old, h1, h2)){
292 case DCCP_PKT_RESPONSE:
293 dbgprintf(2,"Packet Type: Response\n");
294 if(!handle_response(new,old,h1,h2)){
299 if(!handle_data(new,old,h1,h2)){
303 case DCCP_PKT_DATAACK:
304 dbgprintf(2,"Packet Type: DataAck\n");
305 if(!handle_dataack(new,old,h1,h2)){
310 dbgprintf(2,"Packet Type: Ack\n");
311 if(!handle_ack(new,old,h1,h2)){
315 case DCCP_PKT_CLOSEREQ:
316 dbgprintf(2,"Packet Type: CloseReq\n");
317 if(!handle_closereq(new,old,h1,h2)){
322 dbgprintf(2,"Packet Type: Close\n");
323 if(!handle_close(new,old,h1,h2)){
328 dbgprintf(2,"Packet Type: Reset\n");
329 if(!handle_reset(new,old,h1,h2)){
334 dbgprintf(2,"Packet Type: Sync\n");
335 if(!handle_sync(new,old,h1,h2)){
339 case DCCP_PKT_SYNCACK:
340 dbgprintf(2,"Packet Type: SyncAck\n");
341 if(!handle_syncack(new,old,h1,h2)){
346 dbgprintf(0,"Invalid DCCP Packet!!\n");
351 /*Compute TCP checksums*/
352 if(new->id_len==IP4_ADDR_LEN){
354 tcph->check=ipv4_pseudohdr_chksum(new->data,
355 new->length, new->dest_id, new->src_id, 6);
356 }else if(new->id_len==IP6_ADDR_LEN){
358 tcph->check=ipv6_pseudohdr_chksum(new->data,
359 new->length, new->dest_id, new->src_id, 6);
362 dbgprintf(2,"Unknown ID Length, can't do checksums\n");
368 int handle_request(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
371 struct dccp_hdr *dccph;
372 struct dccp_hdr_ext *dccphex;
376 const u_char* dccpopt;
379 if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext)+sizeof(struct dccp_hdr_request)){
383 /*cast header pointers*/
384 tcph=(struct tcphdr*)new->data;
385 dccph=(struct dccp_hdr*)old->data;
386 dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
388 /*determine data length*/
389 datalength=old->length - dccph->dccph_doff*4;
391 /*Process DCCP Options*/
392 dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext)+sizeof(struct dccp_hdr_request);
393 optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr)-sizeof(struct dccp_hdr_ext)-sizeof(struct dccp_hdr_request);
394 if(!parse_options(dccpopt,optlen,old,h1,h2)){
400 tcph->window=htons(0);
402 tcph->ack_seq=htonl(0);
404 tcph->seq=htonl(initialize_hcon(h1, ntohl(dccphex->dccph_seq_low)));
406 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),datalength, dccph->dccph_type));
413 /* add Sack-permitted option, if relevant*/
415 tcpopt=(u_char*)(new->data + tcph->doff*4);
423 new->length=tcph->doff*4;
427 int handle_response(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
430 struct dccp_hdr *dccph;
431 struct dccp_hdr_ext *dccphex;
432 struct dccp_hdr_ack_bits *dccphack;
435 const u_char* dccpopt;
438 if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext)
439 + sizeof(struct dccp_hdr_ack_bits)+sizeof(struct dccp_hdr_request)){
443 /*cast header pointers*/
444 tcph=(struct tcphdr*)new->data;
445 dccph=(struct dccp_hdr*)old->data;
446 dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
447 dccphack=(struct dccp_hdr_ack_bits*)(old->data+ sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
449 /*Process DCCP Options*/
450 dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) +
451 sizeof(struct dccp_hdr_ack_bits) + sizeof(struct dccp_hdr_request);
452 optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext)
453 - sizeof(struct dccp_hdr_ack_bits) - sizeof(struct dccp_hdr_request);
454 if(!parse_options(dccpopt,optlen,old,h1,h2)){
460 dbgprintf(0,"Warning: DCCP Response without a Request!!\n");
462 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
463 h1->high_ack=ntohl(tcph->ack_seq);
465 tcph->window=htons(0);
468 tcph->seq=htonl(initialize_hcon(h1, ntohl(dccphex->dccph_seq_low)));
475 /* add Sack-permitted option, if relevant*/
477 tcpopt=(u_char*)(new->data + tcph->doff*4);
484 new->length=tcph->doff*4;
488 int handle_dataack(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
491 struct dccp_hdr *dccph;
492 struct dccp_hdr_ext *dccphex;
493 struct dccp_hdr_ack_bits *dccphack;
498 const u_char* dccpopt;
501 if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
505 /*cast header pointers*/
506 tcph=(struct tcphdr*)new->data;
507 dccph=(struct dccp_hdr*)old->data;
508 dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
509 dccphack=(struct dccp_hdr_ack_bits*)(old->data+ sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
511 /*determine data length*/
512 datalength=old->length - dccph->dccph_doff*4;
513 pd=old->data + dccph->dccph_doff*4;
515 /*Process DCCP Options*/
516 dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
517 optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
518 if(!parse_options(dccpopt,optlen,old,h1,h2)){
524 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
526 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
528 h1->high_ack=ntohl(tcph->ack_seq);
529 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),datalength, dccph->dccph_type));
531 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
534 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
535 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low),h1);
544 npd=new->data + tcph->doff*4;
545 memcpy(npd, pd, datalength);
548 new->length=tcph->doff*4 + datalength;
552 int handle_ack(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
555 struct dccp_hdr *dccph;
556 struct dccp_hdr_ext *dccphex;
557 struct dccp_hdr_ack_bits *dccphack;
559 const u_char* dccpopt;
562 if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
566 /*cast header pointers*/
567 tcph=(struct tcphdr*)new->data;
568 dccph=(struct dccp_hdr*)old->data;
569 dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
570 dccphack=(struct dccp_hdr_ack_bits*)(old->data+ sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
572 /*Process DCCP Options*/
573 dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
574 optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
575 if(!parse_options(dccpopt,optlen,old,h1,h2)){
581 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
583 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
585 h1->high_ack=ntohl(tcph->ack_seq);
586 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
588 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*1400);
589 if(-interp_ack_vect((u_char*)dccph)*1400 > 65535){
590 dbgprintf(0,"Note: TCP Window Overflow @ %d.%d\n", (int)old->h->ts.tv_sec, (int)old->h->ts.tv_usec);
594 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
595 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low),h1);
605 new->length=tcph->doff*4 + 1;
609 int handle_closereq(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
612 struct dccp_hdr *dccph;
613 struct dccp_hdr_ext *dccphex;
614 struct dccp_hdr_ack_bits *dccphack;
616 const u_char* dccpopt;
619 if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
623 /*cast header pointers*/
624 tcph=(struct tcphdr*)new->data;
625 dccph=(struct dccp_hdr*)old->data;
626 dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
627 dccphack=(struct dccp_hdr_ack_bits*)(old->data+ sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
629 /*Process DCCP Options*/
630 dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
631 optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
632 if(!parse_options(dccpopt,optlen,old,h1,h2)){
638 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
640 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
642 h1->high_ack=ntohl(tcph->ack_seq);
643 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
645 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
648 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
649 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low),h1);
659 new->length=tcph->doff*4;
663 int handle_close(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
666 struct dccp_hdr *dccph;
667 struct dccp_hdr_ext *dccphex;
668 struct dccp_hdr_ack_bits *dccphack;
670 const u_char* dccpopt;
673 if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
677 /*cast header pointers*/
678 tcph=(struct tcphdr*)new->data;
679 dccph=(struct dccp_hdr*)old->data;
680 dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
681 dccphack=(struct dccp_hdr_ack_bits*)(old->data+ sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
683 /*Process DCCP Options*/
684 dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
685 optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
686 if(!parse_options(dccpopt,optlen,old,h1,h2)){
691 update_state(h1,CLOSE);
693 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
695 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
697 h1->high_ack=ntohl(tcph->ack_seq);
698 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
700 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
703 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
704 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low),h1);
714 new->length=tcph->doff*4;
718 int handle_reset(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
721 struct dccp_hdr *dccph;
722 struct dccp_hdr_ext *dccphex;
723 struct dccp_hdr_ack_bits *dccphack;
725 const u_char* dccpopt;
728 if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
732 /*cast header pointers*/
733 tcph=(struct tcphdr*)new->data;
734 dccph=(struct dccp_hdr*)old->data;
735 dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
736 dccphack=(struct dccp_hdr_ack_bits*)(old->data+ sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
738 /*Process DCCP Options*/
739 dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
740 optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
741 if(!parse_options(dccpopt,optlen,old,h1,h2)){
746 if(h2->state==CLOSE){
747 update_state(h1,CLOSE);
750 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
752 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
754 h1->high_ack=ntohl(tcph->ack_seq);
755 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
757 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
760 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
761 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low),h1);
771 new->length=tcph->doff*4;
775 int handle_sync(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
778 struct dccp_hdr *dccph;
779 struct dccp_hdr_ext *dccphex;
780 struct dccp_hdr_ack_bits *dccphack;
782 const u_char* dccpopt;
785 if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
789 /*cast header pointers*/
790 tcph=(struct tcphdr*)new->data;
791 dccph=(struct dccp_hdr*)old->data;
792 dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
793 dccphack=(struct dccp_hdr_ack_bits*)(old->data+ sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
795 /*Process DCCP Options*/
796 dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
797 optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
798 if(!parse_options(dccpopt,optlen,old,h1,h2)){
804 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
806 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
808 h1->high_ack=ntohl(tcph->ack_seq);
809 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),0,dccph->dccph_type));
811 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
813 tcph->window=htons(0);
816 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
817 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low),h1);
827 new->length=tcph->doff*4;
831 int handle_syncack(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
834 struct dccp_hdr *dccph;
835 struct dccp_hdr_ext *dccphex;
836 struct dccp_hdr_ack_bits *dccphack;
838 const u_char* dccpopt;
841 if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
845 /*cast header pointers*/
846 tcph=(struct tcphdr*)new->data;
847 dccph=(struct dccp_hdr*)old->data;
848 dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
849 dccphack=(struct dccp_hdr_ack_bits*)(old->data+ sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
851 /*Process DCCP Options*/
852 dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
853 optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
854 if(!parse_options(dccpopt,optlen,old,h1,h2)){
860 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
862 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
864 h1->high_ack=ntohl(tcph->ack_seq);
865 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),0,dccph->dccph_type));
867 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
869 tcph->window=htons(0);
872 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
873 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low),h1);
883 new->length=tcph->doff*4;
887 int handle_data(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
890 struct dccp_hdr *dccph;
891 struct dccp_hdr_ext *dccphex;
896 const u_char* dccpopt;
899 if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext)){
903 /*cast header pointers*/
904 tcph=(struct tcphdr*)new->data;
905 dccph=(struct dccp_hdr*)old->data;
906 dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
908 /*determine data length*/
909 datalength=old->length - dccph->dccph_doff*4;
910 pd=old->data + dccph->dccph_doff*4;
912 /*Process DCCP Options*/
913 dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext);
914 optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext);
915 if(!parse_options(dccpopt,optlen,old,h1,h2)){
920 tcph->ack_seq=htonl(h1->high_ack);
921 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),datalength, dccph->dccph_type));
928 npd=new->data + tcph->doff*4;
929 memcpy(npd, pd, datalength);
932 new->length=tcph->doff*4 + datalength;
936 int parse_options(const u_char* opt_start, int len, const struct const_packet* pkt,
937 struct hcon* A, struct hcon* B)
945 /*setup pointer to DCCP options and determine how long the options are*/
951 /*One byte options (no length)*/
958 /*Check option length*/
961 dbgprintf(0, "Warning: Option would extend into packet data\n");
965 dbgprintf(0, "Warning: Bad Option!\n");
969 /*Ack Vector Option*/
970 if(*opt==38 || *opt==39){
971 if(B->type==UNKNOWN){
974 dbgprintf(1,"Half-connection from %s:%i to %s:%i probably using CCID 2\n",
975 pkt->print_id(buf1,100,pkt->dest_id,pkt->id_len),ntohs(B->port),
976 pkt->print_id(buf2,100,pkt->src_id,pkt->id_len), ntohs(A->port));
978 dbgprintf(1,"Half-connection from port %i to %i probably using CCID 2\n",
979 ntohs(B->port),ntohs(A->port));
986 if(B->type==UNKNOWN){
989 dbgprintf(1,"Half-connection from %s:%i to %s:%i probably using CCID 3\n",
990 pkt->print_id(buf1,100,pkt->dest_id,pkt->id_len),ntohs(B->port),
991 pkt->print_id(buf2,100,pkt->src_id,pkt->id_len), ntohs(A->port));
993 dbgprintf(1,"Half-connection from port %i to %i probably using CCID 3\n",
994 ntohs(B->port),ntohs(A->port));
999 /*Feature negotation*/
1002 if(!process_feature(opt+2,length-2,FALSE,TRUE,pkt,A,B)){
1008 if(!process_feature(opt+2,length-2,TRUE,TRUE,pkt,A,B)){
1014 if(!process_feature(opt+2,length-2,FALSE,FALSE,pkt,A,B)){
1020 if(!process_feature(opt+2,length-2,TRUE,FALSE,pkt,A,B)){
1032 int process_feature(const u_char* feat, int len, int confirm, int L,
1033 const struct const_packet* pkt, struct hcon* A, struct hcon* B)
1060 dbgprintf(1,"Half-connection from %s:%i to %s:%i using CCID %i\n",
1061 pkt->print_id(buf1,100,pkt->dest_id,pkt->id_len),ntohs(B->port),
1062 pkt->print_id(buf2,100,pkt->src_id,pkt->id_len), ntohs(A->port), *val);
1064 dbgprintf(1,"Half-connection from port %i to %i using CCID %i\n",
1065 ntohs(B->port),ntohs(A->port), *val);
1070 dbgprintf(1,"Half-connection from %s:%i to %s:%i using CCID %i\n",
1071 pkt->print_id(buf1,100,pkt->src_id,pkt->id_len),ntohs(A->port),
1072 pkt->print_id(buf2,100,pkt->dest_id,pkt->id_len), ntohs(B->port), *val);
1074 dbgprintf(1,"Half-connection from port %i to %i using CCID %i\n",
1075 ntohs(A->port),ntohs(B->port), *val);
1081 /*Short sequence nums*/
1082 if(confirm==TRUE && *val==1){
1085 dbgprintf(0,"Error: DCCP is trying to turn on short sequence numbers\n"
1086 " for the connection between %i and %i. We do not support this.\n"
1087 " This connection will be ignored.",ntohs(A->port),ntohs(B->port));
1095 /*Ack Vector to SACK Option*/
1096 void ack_vect2sack(struct hcon *hcn, struct tcphdr *tcph, u_char* tcpopts, u_char* dccphdr,
1097 d_seq_num dccpack, struct hcon* o_hcn)
1099 int hdrlen=((struct dccp_hdr*)dccphdr)->dccph_doff*4;
1116 /*setup pointer to DCCP options and determine how long the options are*/
1117 optlen=hdrlen-sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
1118 opt=dccphdr + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
1124 /*setup tcp pointers*/
1130 pL=(u_int32_t*)temp;
1133 /*setup tcp control variables*/
1142 /*One byte options (no length)*/
1151 dbgprintf(0, "Warning: Option would extend into packet data\n");
1155 /*Ack Vector Option*/
1156 if(*opt==38 || *opt==39){
1159 /*loop through Vector*/
1161 /*ack vector works BACKWARDS through time*/
1163 if((*cur & 0xC0)==0xC0 || (*cur & 0xC0)==0x40){ //lost packet
1164 if(cont){ /*end a SACK run, if one is started*/
1165 bR=convert_ack(hcn, bp,o_hcn);
1175 bp= bp - (*cur & 0x3F)- 1;
1178 if((*cur & 0xC0)==0x00){ //received packet
1179 if(!cont){ /*if no SACK run and we can start another one, do so*/
1181 bL=convert_ack(hcn, bp, o_hcn);
1187 bp = bp -(*cur & 0x3F)- 1;
1198 /*if we are in the middle of a SACK run, close it*/
1200 bR=convert_ack(hcn, bp,o_hcn);
1208 /*adjust length if the option is actually added*/
1217 dbgprintf(0, "dccp2tcp version %.1f\n",DCCP2TCP_VERSION);
1218 dbgprintf(0, "Copyright (C) %i Samuel Jero <sj323707@ohio.edu>\n",COPYRIGHT_YEAR);
1219 dbgprintf(0, "This program comes with ABSOLUTELY NO WARRANTY.\n");
1220 dbgprintf(0, "This is free software, and you are welcome to\n");
1221 dbgprintf(0, "redistribute it under certain conditions.\n");
1225 /*Usage information for program*/
1228 dbgprintf(0,"Usage: dccp2tcp [-v] [-h] [-V] [-y] [-g] [-s] dccp_file tcp_file\n");
1229 dbgprintf(0, " -v verbose. May be repeated for additional verbosity.\n");
1230 dbgprintf(0, " -V Version information\n");
1231 dbgprintf(0, " -h Help\n");
1232 dbgprintf(0, " -y Yellow line is highest ACK\n");
1233 dbgprintf(0, " -g Green line is highest ACK\n");
1234 dbgprintf(0, " -s convert ACK Vectors to SACKS\n");
1239 void dbgprintf(int level, const char *fmt, ...)
1243 va_start(args, fmt);
1244 vfprintf(stderr, fmt, args);