1 /******************************************************************************
6 Description: Program to convert a DCCP flow to a TCP flow for DCCP analysis via
11 2)DCCP MUST use 48 bit sequence numbers
12 3)Checksums are not computed (they are zeroed)
13 4)DCCP DATA packets are not implemented (Linux doesn't use them)
14 5)DCCP Ack packets show up as TCP packets containing one byte
15 ******************************************************************************/
19 int debug=0; /*set to 1 to turn on debugging information*/
20 int yellow=0; /*tcptrace yellow line as currently acked packet*/
21 int green=0; /*tcptrace green line as currently acked packet*/
22 int sack=0; /*add TCP SACKS*/
24 pcap_t* in; /*libpcap input file discriptor*/
25 pcap_dumper_t *out; /*libpcap output file discriptor*/
26 struct connection *chead; /*connection list*/
30 void handle_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes);
31 int convert_packet(struct packet *new, const struct const_packet* old);
32 unsigned int interp_ack_vect(u_char* hdr);
33 u_int32_t initialize_seq(struct host *seq, __be32 initial);
34 u_int32_t add_new_seq(struct host *seq, __be32 num, int size, enum dccp_pkt_type type);
35 u_int32_t convert_ack(struct host *seq, __be32 num);
36 int acked_packet_size(struct host *seq, __be32 num);
37 void ack_vect2sack(struct host *seq, struct tcphdr *tcph, u_char* tcpopts, u_char* dccphdr, __be32 dccpack);
40 /*Parse commandline options and open files*/
41 int main(int argc, char *argv[])
48 /*parse commandline options*/
49 if(argc<3 || argc > 9){
50 dbgprintf(0, "Usage: dccp2tcp dccp_file tcp_file [-d] [-y] [-g] [-s]\n");
54 /*loop through commandline options*/
55 for(int i=1; i < argc; i++){
56 if(argv[i][0]!='-' || (argv[i][0]=='-' && strlen(argv[i])==1)){
57 if(dfile==NULL || argv[i][0]=='-'){
58 /*assign first non-dash (or only dash) argument to the dccp file*/
62 tfile=argv[i]; /*assign second non-dash argument to the dccp file*/
64 dbgprintf(0,"Usage: dccp2tcp dccp_file tcp_file [-d] [-y] [-g] [-s]\n");
69 if(argv[i][1]=='d' && strlen(argv[i])==2){ /*debug option*/
72 if(argv[i][1]=='y' && strlen(argv[i])==2){ /*yellow option*/
75 if(argv[i][1]=='g' && strlen(argv[i])==2){ /*green option*/
78 if(argv[i][1]=='s' && strlen(argv[i])==2){ /*sack option*/
84 if(dfile==NULL || tfile==NULL){
85 dbgprintf(0,"Usage: dccp2tcp dccp_file tcp_file [-d] [-y] [-g] [-s]\n");
89 /*all options validated*/
92 dbgprintf(1,"Debug On\n");
94 dbgprintf(1,"Tcptrace green line at highest acknowledgment\n");
96 dbgprintf(1,"Tcptrace green line at highest acknowledged acknowledgment\n");
99 dbgprintf(1,"Tcptrace yellow line at highest acknowledgment\n");
101 dbgprintf(1,"Tcptrace yellow line window value (a made up number)\n");
104 dbgprintf(1,"Adding TCP SACKS\n");
106 dbgprintf(1,"Input file: %s\n", dfile);
107 dbgprintf(1,"Output file: %s\n", tfile);
110 /*attempt to open input file*/
111 in=pcap_open_offline(dfile, erbuffer);
113 dbgprintf(0,"Error opening input file\n");
117 /*attempt to open output file*/
118 out=pcap_dump_open(in,tfile);
120 dbgprintf(0,"Error opening output file\n");
126 u_char *user=(u_char*)out;
127 pcap_loop(in, -1, handle_packet, user);
131 pcap_dump_close(out);
133 /*Delete all connections*/
134 cleanup_connections();
139 /*call back function for pcap_loop--do basic packet handling*/
140 void handle_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
143 struct pcap_pkthdr nh;
146 struct const_packet old;
148 /*Determine the link type for this packet*/
149 link_type=pcap_datalink(in);
151 /*create new libpcap header*/
152 memcpy(&nh, h, sizeof(struct pcap_pkthdr));
154 /*Setup packet structs*/
156 old.length=h->caplen;
161 new.length=MAX_PACKET;
165 /*create buffer for new packet*/
166 new.data=ndata=malloc(MAX_PACKET);
168 dbgprintf(0,"Error: Couldn't allocate Memory\n");
172 /*make sure the packet is all zero*/
173 memset(new.data, 0, MAX_PACKET);
175 /*do all the fancy conversions*/
176 if(!do_encap(link_type, &new, &old)){
182 pcap_dump(user,&nh, ndata);
189 /*do all the dccp to tcp conversions*/
190 int convert_packet(struct packet *new, const struct const_packet* old)
193 struct dccp_hdr *dccph;
194 struct dccp_hdr_ext *dccphex;
195 struct dccp_hdr_ack_bits *dccphack;
196 struct host *h1=NULL;
197 struct host *h2=NULL;
205 if(!new || !old || !new->data || !old->data || !new->h || !old->h){
206 dbgprintf(0,"Error: Convert Packet Function given bad data!\n");
210 if(old->length < (sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext)) || new->length < sizeof(struct dccp_hdr)){
211 dbgprintf(0, "Error: DCCP Packet Too short!\n");
215 /*cast header pointers*/
216 tcph=(struct tcphdr*)new->data;
217 dccph=(struct dccp_hdr*)old->data;
218 dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
219 dccphack=(struct dccp_hdr_ack_bits*)(old->data+ sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
221 dbgprintf(2,"Sequence Number: %llu\n", (unsigned long long)
222 (((unsigned long)ntohs(dccph->dccph_seq)<<32) + ntohl(dccphex->dccph_seq_low)));
225 if(get_host(new->src_id, new->dest_id, new->id_len,
226 dccph->dccph_sport, dccph->dccph_dport, &h1, &h2)){
227 dbgprintf(0,"Error: Can't Get Hosts!\n");
230 if(h1==NULL || h2==NULL){
231 dbgprintf(0, "Error: Can't Get Hosts!\n");
235 /*Ensure packet is at least as large as DCCP header*/
236 if(old->length < dccph->dccph_doff*4){
237 dbgprintf(0, "Error: DCCP Header truncated\n");
240 if(dccph->dccph_type!=DCCP_PKT_DATA &&
241 old->length < (sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) +
242 sizeof(struct dccp_hdr_ack_bits))){
243 dbgprintf(0, "Error: DCCP Packet Too short!\n");
246 /*determine data length*/
247 datalength=old->length - dccph->dccph_doff*4;
248 pd=old->data + dccph->dccph_doff*4;
250 /*set TCP standard features*/
251 tcph->source=dccph->dccph_sport;
252 tcph->dest=dccph->dccph_dport;
254 tcph->check=htonl(0);
257 /*Adjust TCP advertised window size*/
259 tcph->window=htons(30000);
262 /*make changes by packet type*/
263 if(dccph->dccph_type==DCCP_PKT_REQUEST){//DCCP REQUEST -->TCP SYN
264 dbgprintf(2,"Packet Type: Request\n");
267 tcph->window=htons(0);
269 tcph->ack_seq=htonl(0);
270 tcph->seq=htonl(initialize_seq(h1, ntohl(dccphex->dccph_seq_low)));
276 /* add Sack-permitted option, if relevant*/
278 tcpopt=(u_char*)(new->data + tcph->doff*4);
290 if(dccph->dccph_type==DCCP_PKT_RESPONSE){//DCCP RESPONSE-->TCP SYN,ACK
291 dbgprintf(2,"Packet Type: Response\n");
292 if(h2->state==OPEN && h1->state==INIT){
293 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
295 tcph->window=htons(0);
297 tcph->seq=htonl(initialize_seq(h1, ntohl(dccphex->dccph_seq_low)));
303 /* add Sack-permitted option, if relevant*/
305 tcpopt=(u_char*)(new->data + tcph->doff*4);
316 if(dccph->dccph_type==DCCP_PKT_DATA){//DCCP DATA----Never seen in packet capture
317 dbgprintf(0,"DCCP Data packet not yet implemented\n");
321 if(dccph->dccph_type==DCCP_PKT_DATAACK){//DCCP DATAACK-->TCP ACK with data
322 dbgprintf(2,"Packet Type: DataAck\n");
324 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
326 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
328 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),datalength, dccph->dccph_type));
330 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
333 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
334 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
344 npd=new->data + tcph->doff*4;
345 memcpy(npd, pd, datalength);
348 len= tcph->doff*4 + datalength;
351 if(dccph->dccph_type==DCCP_PKT_ACK){ //DCCP ACK -->TCP ACK with no data
352 dbgprintf(2,"Packet Type: Ack\n");
354 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
356 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
358 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
360 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*1400);
361 if(-interp_ack_vect((u_char*)dccph)*1400 > 65535){
362 printf("Note: TCP Window Overflow @ %d.%d\n", (int)old->h->ts.tv_sec, (int)old->h->ts.tv_usec);
366 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
367 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
377 len=tcph->doff*4 + 1;
380 if(dccph->dccph_type==DCCP_PKT_CLOSEREQ){//DCCP CLOSEREQ----Never seen in packet capture
381 dbgprintf(0,"DCCP CloseReq not yet implemented\n");
385 if(dccph->dccph_type==DCCP_PKT_CLOSE){//DCCP CLOSE-->TCP FIN,ACK
386 dbgprintf(2,"Packet Type: Close\n");
387 update_state(h1,CLOSE);
389 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
391 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
393 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
395 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
398 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
399 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
412 if(dccph->dccph_type==DCCP_PKT_RESET){//DCCP RESET-->TCP FIN,ACK (only seen at end of connection as CLOSE ACK)
413 if(h2->state==CLOSE){
414 update_state(h1,CLOSE);
416 dbgprintf(2,"Packet Type: Reset\n");
418 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
420 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
422 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
424 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
427 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
428 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
441 if(dccph->dccph_type==DCCP_PKT_SYNC){//DCCP SYNC
442 dbgprintf(2,"Packet Type: Sync\n");
444 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
446 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
448 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),0,dccph->dccph_type));
450 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
452 tcph->window=htons(0);
455 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
456 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
469 if(dccph->dccph_type==DCCP_PKT_SYNCACK){//DCCP SYNACK
470 dbgprintf(2,"Packet Type: SyncAck\n");
472 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
474 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
476 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),0,dccph->dccph_type));
478 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
480 tcph->window=htons(0);
483 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
484 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low));
497 if(dccph->dccph_type==DCCP_PKT_INVALID){//DCCP INVALID----Never seen in packet capture
498 dbgprintf(0,"Invalid DCCP Packet!!\n");
507 /*Parse Ack Vector Options
508 * Returns the Number of packets since last recorded loss*/
509 unsigned int interp_ack_vect(u_char* hdr)
511 int hdrlen=((struct dccp_hdr*)hdr)->dccph_doff*4;
512 //struct dccp_hdr_ext* e=(struct dccp_hdr_ext*)hdr + sizeof(struct dccp_hdr);
521 /*setup pointer to DCCP options and determine how long the options are*/
522 optlen=hdrlen-sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
523 opt=hdr + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
528 /*One byte options (no length)*/
535 /*Check option length*/
538 dbgprintf(0, "Warning: Option would extend into packet data\n");
542 /*Ack Vector Option*/
543 if(*opt==38 || *opt==39){
546 /*loop through Vector*/
548 /*ack vector works BACKWARDS through time*/
550 /*keep track of total packets recieved and if
551 a packet is lost, subtract all packets received
553 if((*cur & 0xC0)==0xC0 || (*cur & 0xC0)==0x40){ //lost packet
558 if((*cur & 0xC0)==0x00){ //received packet
559 bp+= (*cur & 0x3F)+1;
562 if(((*cur& 0xC0)!= 0xC0) && ((*cur& 0xC0)!= 0x00) && ((*cur& 0xC0)!= 0x40)){
563 dbgprintf(1, "Warning: Invalid Ack Vector!! (Linux will handle poorly!)\n");
574 dbgprintf(2,"Ack vector adding: %i\n", additional);
579 /* Setup Sequence Number Structure*/
580 u_int32_t initialize_seq(struct host *seq, __be32 initial)
582 /*set default values*/
587 seq->table=(struct tbl*)malloc(sizeof(struct tbl)*TBL_SZ);
588 if(seq->table==NULL){
589 dbgprintf(0,"Can't Allocate Memory!\n");
593 /*add first sequence number*/
594 seq->table[0].old=initial;
595 seq->table[0].new=initial;
596 seq->table[0].type=DCCP_PKT_REQUEST;
597 seq->table[0].size=0;
598 update_state(seq,OPEN);
603 /*Convert Sequence Numbers*/
604 u_int32_t add_new_seq(struct host *seq, __be32 num, int size, enum dccp_pkt_type type)
608 dbgprintf(0,"ERROR NULL POINTER!\n");
612 if(seq->table==NULL){
613 dbgprintf(1, "Warning: Connection uninitialized\n");
614 return initialize_seq(seq, num);
617 /*account for missing packets*/
618 if(num - seq->table[seq->cur].old +1 >=100){
619 dbgprintf(1,"Missing more than 100 packets!\n");
621 while(seq->table[seq->cur].old +1 < num && seq->table[seq->cur].old +1 > 0){
623 if(num - seq->table[seq->cur].old +1 <100){
624 dbgprintf(1,"Missing Packet: %X\n",seq->table[prev].new+1);
626 seq->cur=(seq->cur+1)%(seq->size);/*find next available table slot*/
627 seq->table[seq->cur].old=seq->table[prev].old+1;
628 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
629 seq->table[seq->cur].size=size;
630 seq->table[seq->cur].type=type;
634 seq->cur=(seq->cur+1)%(seq->size);/*find next available table slot*/
635 seq->table[seq->cur].old=num;
636 seq->table[seq->cur].size=size;
637 seq->table[seq->cur].type=type;
638 if(seq->table[prev].type==DCCP_PKT_REQUEST || seq->table[prev].type==DCCP_PKT_RESPONSE){
639 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
640 seq->table[seq->cur].size=1;
641 return seq->table[prev].new + seq->table[prev].size+1;
643 if(type==DCCP_PKT_DATA || type==DCCP_PKT_DATAACK || type==DCCP_PKT_ACK){
644 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
645 return seq->table[seq->cur].new+1;
647 if(type==DCCP_PKT_SYNC || type==DCCP_PKT_SYNCACK){
648 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
649 return seq->table[seq->cur].new;
651 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
652 return seq->table[seq->cur].new +1;
656 /*Convert Ack Numbers*/
657 u_int32_t convert_ack(struct host *seq, __be32 num)
660 dbgprintf(0,"ERROR NULL POINTER!\n");
664 if(seq->table==NULL){
665 dbgprintf(1, "Warning: Connection uninitialized\n");
666 initialize_seq(seq, num);
669 /*loop through table looking for the DCCP ack number*/
670 for(int i=0; i < seq->size; i++){
671 if(seq->table[i].old==num){
672 return seq->table[i].new + seq->table[i].size + 1; /*TCP acks the sequence number plus 1*/
676 dbgprintf(1, "Error: Address Not Found! looking for: %X\n", num);
681 /* Get size of packet being acked*/
682 int acked_packet_size(struct host *seq, __be32 num)
685 dbgprintf(0,"ERROR NULL POINTER!\n");
689 if(seq->table==NULL){
690 dbgprintf(1, "Warning: Connection uninitialized\n");
691 initialize_seq(seq, num);
694 /*loop through table looking for the DCCP ack number*/
695 for(int i=0; i < seq->size; i++){
696 if(seq->table[i].old==num){
697 return seq->table[i].size;
701 dbgprintf(1, "Error: Address Not Found! looking for: %X\n", num);
706 /*Ack Vector to SACK Option*/
707 void ack_vect2sack(struct host *seq, struct tcphdr *tcph, u_char* tcpopts, u_char* dccphdr, __be32 dccpack)
709 int hdrlen=((struct dccp_hdr*)dccphdr)->dccph_doff*4;
726 /*setup pointer to DCCP options and determine how long the options are*/
727 optlen=hdrlen-sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
728 opt=dccphdr + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
730 /*setup tcp pointers*/
739 /*setup tcp control variables*/
748 /*One byte options (no length)*/
757 dbgprintf(0, "Warning: Option would extend into packet data\n");
761 /*Ack Vector Option*/
762 if(*opt==38 || *opt==39){
765 /*loop through Vector*/
767 /*ack vector works BACKWARDS through time*/
769 if((*cur & 0xC0)==0xC0 || (*cur & 0xC0)==0x40){ //lost packet
770 if(cont){ /*end a SACK run, if one is started*/
771 bR=convert_ack(seq, bp);
781 bp= bp - (*cur & 0x3F)- 1;
784 if((*cur & 0xC0)==0x00){ //received packet
785 if(!cont){ /*if no SACK run and we can start another one, do so*/
787 bL=convert_ack(seq, bp);
793 bp = bp -(*cur & 0x3F)- 1;
804 /*if we are in the middle of a SACK run, close it*/
806 bR=convert_ack(seq, bp);
814 /*adjust length if the option is actually added*/
822 void dbgprintf(int level, const char *fmt, ...)
827 vfprintf(stderr, fmt, args);