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, 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);
64 /*Parse commandline options and open files*/
65 int main(int argc, char *argv[])
72 /*parse commandline options*/
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*/
85 tfile=argv[i]; /*assign second non-dash argument to the dccp file*/
91 if(argv[i][1]=='d' && strlen(argv[i])==2){ /* -d */
94 if(argv[i][1]=='y' && strlen(argv[i])==2){ /* -y */
97 if(argv[i][1]=='g' && strlen(argv[i])==2){ /* -g */
100 if(argv[i][1]=='s' && strlen(argv[i])==2){ /* -s */
103 if(argv[i][1]=='h' && strlen(argv[i])==2){ /* -h */
106 if(argv[i][1]=='V' && strlen(argv[i])==2){ /* -V */
112 if(dfile==NULL || tfile==NULL){
116 /*all options validated*/
119 dbgprintf(1,"Debug On\n");
121 dbgprintf(1,"Tcptrace green line at highest acknowledgment\n");
123 dbgprintf(1,"Tcptrace green line at highest acknowledged acknowledgment\n");
126 dbgprintf(1,"Tcptrace yellow line at highest acknowledgment\n");
128 dbgprintf(1,"Tcptrace yellow line window value (a made up number)\n");
131 dbgprintf(1,"Adding TCP SACKS\n");
133 dbgprintf(1,"Input file: %s\n", dfile);
134 dbgprintf(1,"Output file: %s\n", tfile);
137 /*attempt to open input file*/
138 in=pcap_open_offline(dfile, erbuffer);
140 dbgprintf(0,"Error opening input file\n");
144 /*attempt to open output file*/
145 out=pcap_dump_open(in,tfile);
147 dbgprintf(0,"Error opening output file\n");
153 u_char *user=(u_char*)out;
154 pcap_loop(in, -1, handle_packet, user);
158 pcap_dump_close(out);
160 /*Delete all connections*/
161 cleanup_connections();
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)
170 struct pcap_pkthdr nh;
173 struct const_packet old;
175 /*Determine the link type for this packet*/
176 link_type=pcap_datalink(in);
178 /*create new libpcap header*/
179 memcpy(&nh, h, sizeof(struct pcap_pkthdr));
181 /*Setup packet structs*/
183 old.length=h->caplen;
188 new.length=MAX_PACKET;
192 /*create buffer for new packet*/
193 new.data=ndata=malloc(MAX_PACKET);
195 dbgprintf(0,"Error: Couldn't allocate Memory\n");
199 /*make sure the packet is all zero*/
200 memset(new.data, 0, MAX_PACKET);
202 /*do all the fancy conversions*/
203 if(!do_encap(link_type, &new, &old)){
209 pcap_dump(user,&nh, ndata);
215 /*do all the dccp to tcp conversions*/
216 int convert_packet(struct packet *new, const struct const_packet* old)
219 struct dccp_hdr *dccph;
220 struct dccp_hdr_ext *dccphex;
221 struct hcon *h1=NULL;
222 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,
252 dccph->dccph_sport, dccph->dccph_dport, &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");
261 /*set TCP standard features*/
262 tcph->source=dccph->dccph_sport;
263 tcph->dest=dccph->dccph_dport;
265 tcph->check=htonl(0);
268 /*Adjust TCP advertised window size*/
270 tcph->window=htons(30000);
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)){
281 case DCCP_PKT_RESPONSE:
282 dbgprintf(2,"Packet Type: Response\n");
283 if(!handle_response(new,old,h1,h2)){
288 if(!handle_data(new,old,h1,h2)){
292 case DCCP_PKT_DATAACK:
293 dbgprintf(2,"Packet Type: DataAck\n");
294 if(!handle_dataack(new,old,h1,h2)){
299 dbgprintf(2,"Packet Type: Ack\n");
300 if(!handle_ack(new,old,h1,h2)){
304 case DCCP_PKT_CLOSEREQ:
305 dbgprintf(2,"Packet Type: CloseReq\n");
306 if(!handle_closereq(new,old,h1,h2)){
311 dbgprintf(2,"Packet Type: Close\n");
312 if(!handle_close(new,old,h1,h2)){
317 dbgprintf(2,"Packet Type: Reset\n");
318 if(!handle_reset(new,old,h1,h2)){
323 dbgprintf(2,"Packet Type: Sync\n");
324 if(!handle_sync(new,old,h1,h2)){
328 case DCCP_PKT_SYNCACK:
329 dbgprintf(2,"Packet Type: SyncAck\n");
330 if(!handle_syncack(new,old,h1,h2)){
335 dbgprintf(0,"Invalid DCCP Packet!!\n");
340 /*Compute TCP checksums*/
341 if(new->id_len==IP4_ADDR_LEN){
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){
347 tcph->check=ipv6_pseudohdr_chksum(new->data,
348 new->length, new->dest_id, new->src_id, 6);
351 dbgprintf(2,"Unknown ID Length, can't do checksums\n");
357 int handle_request(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
360 struct dccp_hdr *dccph;
361 struct dccp_hdr_ext *dccphex;
365 const u_char* dccpopt;
368 if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext)+sizeof(struct dccp_hdr_request)){
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));
377 /*determine data length*/
378 datalength=old->length - dccph->dccph_doff*4;
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)){
389 tcph->window=htons(0);
391 tcph->ack_seq=htonl(0);
393 tcph->seq=htonl(initialize_hcon(h1, ntohl(dccphex->dccph_seq_low)));
395 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),datalength, dccph->dccph_type));
402 /* add Sack-permitted option, if relevant*/
404 tcpopt=(u_char*)(new->data + tcph->doff*4);
412 new->length=tcph->doff*4;
416 int handle_response(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
419 struct dccp_hdr *dccph;
420 struct dccp_hdr_ext *dccphex;
421 struct dccp_hdr_ack_bits *dccphack;
424 const u_char* dccpopt;
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)){
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));
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)){
449 dbgprintf(0,"Warning: DCCP Response without a Request!!\n");
451 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
452 h1->high_ack=ntohl(tcph->ack_seq);
454 tcph->window=htons(0);
457 tcph->seq=htonl(initialize_hcon(h1, ntohl(dccphex->dccph_seq_low)));
464 /* add Sack-permitted option, if relevant*/
466 tcpopt=(u_char*)(new->data + tcph->doff*4);
473 new->length=tcph->doff*4;
477 int handle_dataack(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
480 struct dccp_hdr *dccph;
481 struct dccp_hdr_ext *dccphex;
482 struct dccp_hdr_ack_bits *dccphack;
487 const u_char* dccpopt;
490 if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
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));
500 /*determine data length*/
501 datalength=old->length - dccph->dccph_doff*4;
502 pd=old->data + dccph->dccph_doff*4;
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)){
513 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
515 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
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));
520 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
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);
533 npd=new->data + tcph->doff*4;
534 memcpy(npd, pd, datalength);
537 new->length=tcph->doff*4 + datalength;
541 int handle_ack(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
544 struct dccp_hdr *dccph;
545 struct dccp_hdr_ext *dccphex;
546 struct dccp_hdr_ack_bits *dccphack;
548 const u_char* dccpopt;
551 if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
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));
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)){
570 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
572 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
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));
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);
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);
594 new->length=tcph->doff*4 + 1;
598 int handle_closereq(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
601 struct dccp_hdr *dccph;
602 struct dccp_hdr_ext *dccphex;
603 struct dccp_hdr_ack_bits *dccphack;
605 const u_char* dccpopt;
608 if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
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));
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)){
627 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
629 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
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));
634 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
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);
648 new->length=tcph->doff*4;
652 int handle_close(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
655 struct dccp_hdr *dccph;
656 struct dccp_hdr_ext *dccphex;
657 struct dccp_hdr_ack_bits *dccphack;
659 const u_char* dccpopt;
662 if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
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));
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)){
680 update_state(h1,CLOSE);
682 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
684 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
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));
689 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
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);
703 new->length=tcph->doff*4;
707 int handle_reset(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
710 struct dccp_hdr *dccph;
711 struct dccp_hdr_ext *dccphex;
712 struct dccp_hdr_ack_bits *dccphack;
714 const u_char* dccpopt;
717 if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
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));
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)){
735 if(h2->state==CLOSE){
736 update_state(h1,CLOSE);
739 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
741 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
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));
746 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
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);
760 new->length=tcph->doff*4;
764 int handle_sync(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
767 struct dccp_hdr *dccph;
768 struct dccp_hdr_ext *dccphex;
769 struct dccp_hdr_ack_bits *dccphack;
771 const u_char* dccpopt;
774 if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
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));
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)){
793 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
795 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
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));
800 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
802 tcph->window=htons(0);
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);
816 new->length=tcph->doff*4;
820 int handle_syncack(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
823 struct dccp_hdr *dccph;
824 struct dccp_hdr_ext *dccphex;
825 struct dccp_hdr_ack_bits *dccphack;
827 const u_char* dccpopt;
830 if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
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));
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)){
849 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
851 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
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));
856 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
858 tcph->window=htons(0);
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);
872 new->length=tcph->doff*4;
876 int handle_data(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
879 struct dccp_hdr *dccph;
880 struct dccp_hdr_ext *dccphex;
885 const u_char* dccpopt;
888 if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext)){
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));
897 /*determine data length*/
898 datalength=old->length - dccph->dccph_doff*4;
899 pd=old->data + dccph->dccph_doff*4;
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)){
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));
917 npd=new->data + tcph->doff*4;
918 memcpy(npd, pd, datalength);
921 new->length=tcph->doff*4 + datalength;
925 int parse_options(const u_char* opt_start, int len, struct hcon* A, struct hcon* B)
931 /*setup pointer to DCCP options and determine how long the options are*/
937 /*One byte options (no length)*/
944 /*Check option length*/
947 dbgprintf(0, "Warning: Option would extend into packet data\n");
951 dbgprintf(0, "Warning: Bad Option!\n");
955 /*Ack Vector Option*/
956 if(*opt==38 || *opt==39){
965 /*Feature negotation*/
968 if(!process_feature(opt+2,length-2,FALSE,TRUE,A,B)){
974 if(!process_feature(opt+2,length-2,TRUE,TRUE,A,B)){
980 if(!process_feature(opt+2,length-2,FALSE,FALSE,A,B)){
986 if(!process_feature(opt+2,length-2,TRUE,FALSE,A,B)){
998 int process_feature(const u_char* feat, int len, int confirm, int L, struct hcon* A, struct hcon* B)
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");
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)
1042 int hdrlen=((struct dccp_hdr*)dccphdr)->dccph_doff*4;
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);
1067 /*setup tcp pointers*/
1073 pL=(u_int32_t*)temp;
1076 /*setup tcp control variables*/
1085 /*One byte options (no length)*/
1094 dbgprintf(0, "Warning: Option would extend into packet data\n");
1098 /*Ack Vector Option*/
1099 if(*opt==38 || *opt==39){
1102 /*loop through Vector*/
1104 /*ack vector works BACKWARDS through time*/
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);
1118 bp= bp - (*cur & 0x3F)- 1;
1121 if((*cur & 0xC0)==0x00){ //received packet
1122 if(!cont){ /*if no SACK run and we can start another one, do so*/
1124 bL=convert_ack(hcn, bp, o_hcn);
1130 bp = bp -(*cur & 0x3F)- 1;
1141 /*if we are in the middle of a SACK run, close it*/
1143 bR=convert_ack(hcn, bp,o_hcn);
1151 /*adjust length if the option is actually added*/
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");
1166 /*Usage information for program*/
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");
1180 void dbgprintf(int level, const char *fmt, ...)
1184 va_start(args, fmt);
1185 vfprintf(stderr, fmt, args);