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)Only implements those packet types normally used in a session
14 5)DCCP Ack packets show up as TCP packets containing one byte
15 6)Very little error checking of packet headers
16 ******************************************************************************/
20 int debug=0; /*set to 1 to turn on debugging information*/
21 int yellow=0; /*tcptrace yellow line as currently acked packet*/
22 int green=0; /*tcptrace green line as currently acked packet*/
23 int sack=0; /*add TCP SACKS*/
25 pcap_t* in; /*libpcap input file discriptor*/
26 pcap_dumper_t *out; /*libpcap output file discriptor*/
27 struct connection *chead; /*connection list*/
31 void PcapSavePacket(struct pcap_pkthdr *h, u_char *data);
32 void process_packets();
33 void handle_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes);
34 int convert_packet(struct packet *new, const struct const_packet* old);
35 unsigned int interp_ack_vect(u_char* hdr);
36 u_int32_t initialize_seq(struct host *seq, __be16 source, __be32 initial);
37 u_int32_t add_new_seq(struct host *seq, __be32 num, int size, enum dccp_pkt_type type);
38 u_int32_t convert_ack(struct host *seq, __be32 num);
39 int acked_packet_size(struct host *seq, __be32 num);
40 void ack_vect2sack(struct host *seq, struct tcphdr *tcph, u_char* tcpopts, u_char* dccphdr, __be32 dccpack);
43 /*Parse commandline options and open files*/
44 int main(int argc, char *argv[])
51 /*parse commandline options*/
52 if(argc<3 || argc > 9){
53 dbgprintf(0, "Usage: dccp2tcp dccp_file tcp_file [-d] [-y] [-g] [-s]\n");
57 /*loop through commandline options*/
58 for(int i=1; i < argc; i++){
60 if(dfile==NULL){ /*assign first non-dash argument to the dccp file*/
64 tfile=argv[i]; /*assign second non-dash argument to the dccp file*/
66 dbgprintf(0,"Usage: dccp2tcp dccp_file tcp_file [-d] [-y] [-g] [-s]\n");
71 if(argv[i][1]=='d' && strlen(argv[i])==2){ /*debug option*/
74 if(argv[i][1]=='y' && strlen(argv[i])==2){ /*yellow option*/
77 if(argv[i][1]=='g' && strlen(argv[i])==2){ /*green option*/
80 if(argv[i][1]=='s' && strlen(argv[i])==2){ /*sack option*/
86 if(dfile==NULL || tfile==NULL){
87 dbgprintf(0,"Usage: dccp2tcp dccp_file tcp_file [-d] [-y] [-g] [-s]\n");
91 /*all options validated*/
94 dbgprintf(1,"Debug On\n");
96 dbgprintf(1,"Tcptrace green line at highest acknowledgment\n");
98 dbgprintf(1,"Tcptrace green line at highest acknowledged acknowledgment\n");
101 dbgprintf(1,"Tcptrace yellow line at highest acknowledgment\n");
103 dbgprintf(1,"Tcptrace yellow line window value (a made up number)\n");
106 dbgprintf(1,"Adding TCP SACKS\n");
108 dbgprintf(1,"Input file: %s\n", dfile);
109 dbgprintf(1,"Output file: %s\n", tfile);
112 /*attempt to open input file*/
113 in=pcap_open_offline(dfile, erbuffer);
115 dbgprintf(0,"Error opening input file\n");
119 /*attempt to open output file*/
120 out=pcap_dump_open(in,tfile);
122 dbgprintf(0,"Error opening output file\n");
128 u_char *user=(u_char*)out;
129 pcap_loop(in, -1, handle_packet, user);
133 pcap_dump_close(out);
138 /*call back function for pcap_loop--do basic packet handling*/
139 void handle_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
142 struct pcap_pkthdr nh;
145 struct const_packet old;
147 /*Determine the link type for this packet*/
148 link_type=pcap_datalink(in);
150 /*create new libpcap header*/
151 memcpy(&nh, h, sizeof(struct pcap_pkthdr));
153 /*Setup packet structs*/
155 old.length=h->caplen;
158 new.length=MAX_PACKET;
160 /*create buffer for new packet*/
161 new.data=ndata=malloc(MAX_PACKET);
163 dbgprintf(0,"Error: Couldn't allocate Memory\n");
167 /*make sure the packet is all zero*/
168 memset(new.data, 0, MAX_PACKET);
170 /*do all the fancy conversions*/
171 if(!do_encap(link_type, &new, &old)){
177 pcap_dump(user,&nh, ndata);
184 /*do all the dccp to tcp conversions*/
185 int convert_packet(struct packet *new, const struct const_packet* old)
188 struct dccp_hdr *dccph;
189 struct dccp_hdr_ext *dccphex;
190 struct dccp_hdr_ack_bits *dccphack;
191 struct host *h1=NULL;
192 struct host *h2=NULL;
200 if(!new || !old || !new->data || !old->data || !new->h || !old->h){
201 dbgprintf(0,"Error: Convert Packet Function given bad data!\n");
205 if(old->length < sizeof(struct dccp_hdr) || new->length < sizeof(struct dccp_hdr)){
206 dbgprintf(0, "Error: Convert Packet Function given packet of wrong size!\n");
210 /*cast header pointers*/
211 tcph=(struct tcphdr*)new->data;
212 dccph=(struct dccp_hdr*)old->data;
213 dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
214 dccphack=(struct dccp_hdr_ack_bits*)(old->data+ sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
216 dbgprintf(2,"Sequence Number: %llu\n", (unsigned long long)(((unsigned long)ntohs(dccph->dccph_seq)<<32) + ntohl(dccphex->dccph_seq_low)));
219 if(get_host(new->src_id, new->dest_id, dccph->dccph_sport, dccph->dccph_dport, &h1, &h2)){
220 dbgprintf(0,"Error: Can't Get Hosts!\n");
223 if(h1==NULL || h2==NULL){
224 dbgprintf(0, "Error: Can't Get Hosts!\n");
228 /*determine data length*/
229 datalength=old->length - dccph->dccph_doff*4;
230 pd=old->data + dccph->dccph_doff*4;
232 /*set TCP standard features*/
233 tcph->source=dccph->dccph_sport;
234 tcph->dest=dccph->dccph_dport;
236 tcph->check=htonl(0);
239 /*Adjust TCP advertised window size*/
241 tcph->window=htons(30000);
244 /*make changes by packet type*/
245 if(dccph->dccph_type==DCCP_PKT_REQUEST){//DCCP REQUEST -->TCP SYN
246 dbgprintf(2,"Packet Type: Request\n");
249 tcph->window=htons(0);
251 tcph->ack_seq=htonl(0);
252 tcph->seq=htonl(initialize_seq(h1, dccph->dccph_sport, ntohl(dccphex->dccph_seq_low)));
258 /* add Sack-permitted option, if relevant*/
260 tcpopt=(u_char*)(new->data + tcph->doff*4);
272 if(dccph->dccph_type==DCCP_PKT_RESPONSE){//DCCP RESPONSE-->TCP SYN,ACK
273 dbgprintf(2,"Packet Type: Response\n");
274 if(h2->state==OPEN && h1->state==INIT){
275 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
277 tcph->window=htons(0);
279 tcph->seq=htonl(initialize_seq(h1, dccph->dccph_sport, ntohl(dccphex->dccph_seq_low)));
285 /* add Sack-permitted option, if relevant*/
287 tcpopt=(u_char*)(new->data + tcph->doff*4);
298 if(dccph->dccph_type==DCCP_PKT_DATA){//DCCP DATA----Never seen in packet capture
299 dbgprintf(0,"DCCP Data packet not yet implemented\n");
303 if(dccph->dccph_type==DCCP_PKT_DATAACK){//DCCP DATAACK-->TCP ACK with data
304 dbgprintf(2,"Packet Type: DataAck\n");
306 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
308 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
310 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),datalength, dccph->dccph_type));
312 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
315 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
316 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
326 npd=new->data + tcph->doff*4;
327 memcpy(npd, pd, datalength);
330 len= tcph->doff*4 + datalength;
333 if(dccph->dccph_type==DCCP_PKT_ACK){ //DCCP ACK -->TCP ACK with no data
334 dbgprintf(2,"Packet Type: Ack\n");
336 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
338 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
340 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
342 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*1400);
343 if(-interp_ack_vect((u_char*)dccph)*1400 > 65535){
344 printf("Note: TCP Window Overflow @ %d.%d\n", (int)old->h->ts.tv_sec, (int)old->h->ts.tv_usec);
348 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
349 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
359 len=tcph->doff*4 + 1;
362 if(dccph->dccph_type==DCCP_PKT_CLOSEREQ){//DCCP CLOSEREQ----Never seen in packet capture
363 dbgprintf(0,"DCCP CloseReq not yet implemented\n");
367 if(dccph->dccph_type==DCCP_PKT_CLOSE){//DCCP CLOSE-->TCP FIN,ACK
368 dbgprintf(2,"Packet Type: Close\n");
369 update_state(h1,CLOSE);
371 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
373 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
375 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
377 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
380 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
381 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
394 if(dccph->dccph_type==DCCP_PKT_RESET){//DCCP RESET-->TCP FIN,ACK (only seen at end of connection as CLOSE ACK)
395 if(h2->state==CLOSE){
396 update_state(h1,CLOSE);
398 dbgprintf(2,"Packet Type: Reset\n");
400 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
402 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
404 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
406 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
409 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
410 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
423 if(dccph->dccph_type==DCCP_PKT_SYNC){//DCCP SYNC
424 dbgprintf(2,"Packet Type: Sync\n");
426 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
428 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
430 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),0,dccph->dccph_type));
432 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
434 tcph->window=htons(0);
437 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
438 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
451 if(dccph->dccph_type==DCCP_PKT_SYNCACK){//DCCP SYNACK
452 dbgprintf(2,"Packet Type: SyncAck\n");
454 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
456 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
458 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),0,dccph->dccph_type));
460 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
462 tcph->window=htons(0);
465 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
466 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low));
479 if(dccph->dccph_type==DCCP_PKT_INVALID){//DCCP INVALID----Never seen in packet capture
480 dbgprintf(0,"Invalid DCCP Packet!!\n");
489 /*Parse Ack Vector Options
490 * Returns the Number of packets since last recorded loss*/
491 unsigned int interp_ack_vect(u_char* hdr)
493 int hdrlen=((struct dccp_hdr*)hdr)->dccph_doff*4;
494 //struct dccp_hdr_ext* e=(struct dccp_hdr_ext*)hdr + sizeof(struct dccp_hdr);
503 /*setup pointer to DCCP options and determine how long the options are*/
504 optlen=hdrlen-sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
505 opt=hdr + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
511 /*One byte options (no length)*/
518 /*Ack Vector Option*/
519 if(*opt==38 || *opt==39){
522 /*loop through Vector*/
524 /*ack vector works BACKWARDS through time*/
526 /*keep track of total packets recieved and if
527 a packet is lost, subtract all packets received
529 if((*cur & 0xC0)==0xC0 || (*cur & 0xC0)==0x40){ //lost packet
534 if((*cur & 0xC0)==0x00){ //received packet
535 bp+= (*cur & 0x3F)+1;
538 if(((*cur& 0xC0)!= 0xC0) && ((*cur& 0xC0)!= 0x00) && ((*cur& 0xC0)!= 0x40)){
539 dbgprintf(1, "Warning: Invalid Ack Vector!! (Linux will handle poorly!) -- %X\n", *cur);
550 dbgprintf(2,"Ack vector adding: %i\n", additional);
555 /* Setup Sequence Number Structure*/
556 u_int32_t initialize_seq(struct host *seq, __be16 source, __be32 initial)
558 /*set default values*/
563 seq->table=(struct tbl*)malloc(sizeof(struct tbl)*TBL_SZ);
564 if(seq->table==NULL){
565 dbgprintf(0,"Can't Allocate Memory!\n");
569 /*add first sequence number*/
570 seq->table[0].old=initial;
571 seq->table[0].new=initial;
572 seq->table[0].type=DCCP_PKT_REQUEST;
573 seq->table[0].size=0;
574 update_state(seq,OPEN);
579 /*Convert Sequence Numbers*/
580 u_int32_t add_new_seq(struct host *seq, __be32 num, int size, enum dccp_pkt_type type)
584 dbgprintf(0,"ERROR NULL POINTER!\n");
588 if(seq->table==NULL){
589 dbgprintf(1, "Warning: Connection uninitialized\n");
590 return initialize_seq(seq, 0, num);
593 /*account for missing packets*/
594 while(seq->table[seq->cur].old +1 < num && seq->table[seq->cur].old +1 > 0){
596 dbgprintf(1,"Missing Packet: %X\n",seq->table[prev].new+1);
597 seq->cur=(seq->cur+1)%(seq->size);/*find next available table slot*/
598 seq->table[seq->cur].old=seq->table[prev].old+1;
599 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
600 seq->table[seq->cur].size=size;
601 seq->table[seq->cur].type=type;
605 seq->cur=(seq->cur+1)%(seq->size);/*find next available table slot*/
606 seq->table[seq->cur].old=num;
607 seq->table[seq->cur].size=size;
608 seq->table[seq->cur].type=type;
609 if(seq->table[prev].type==DCCP_PKT_REQUEST || seq->table[prev].type==DCCP_PKT_RESPONSE){
610 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
611 seq->table[seq->cur].size=1;
612 return seq->table[prev].new + seq->table[prev].size+1;
614 if(type==DCCP_PKT_DATA || type==DCCP_PKT_DATAACK || type==DCCP_PKT_ACK){
615 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
616 return seq->table[seq->cur].new+1;
618 if(type==DCCP_PKT_SYNC || type==DCCP_PKT_SYNCACK){
619 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
620 return seq->table[seq->cur].new;
622 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
623 return seq->table[seq->cur].new +1;
627 /*Convert Ack Numbers*/
628 u_int32_t convert_ack(struct host *seq, __be32 num)
631 dbgprintf(0,"ERROR NULL POINTER!\n");
635 if(seq->table==NULL){
636 dbgprintf(1, "Warning: Connection uninitialized\n");
637 initialize_seq(seq, 0, num);
640 /*loop through table looking for the DCCP ack number*/
641 for(int i=0; i < seq->size; i++){
642 if(seq->table[i].old==num){
643 return seq->table[i].new + seq->table[i].size + 1; /*TCP acks the sequence number plus 1*/
647 dbgprintf(1, "Error: Address Not Found! looking for: %X\n", num);
652 /* Get size of packet being acked*/
653 int acked_packet_size(struct host *seq, __be32 num)
656 dbgprintf(0,"ERROR NULL POINTER!\n");
660 if(seq->table==NULL){
661 dbgprintf(1, "Warning: Connection uninitialized\n");
662 initialize_seq(seq, 0, num);
665 /*loop through table looking for the DCCP ack number*/
666 for(int i=0; i < seq->size; i++){
667 if(seq->table[i].old==num){
668 return seq->table[i].size;
672 dbgprintf(1, "Error: Address Not Found! looking for: %X\n", num);
677 /*Ack Vector to SACK Option*/
678 void ack_vect2sack(struct host *seq, struct tcphdr *tcph, u_char* tcpopts, u_char* dccphdr, __be32 dccpack)
680 int hdrlen=((struct dccp_hdr*)dccphdr)->dccph_doff*4;
697 /*setup pointer to DCCP options and determine how long the options are*/
698 optlen=hdrlen-sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
699 opt=dccphdr + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
701 /*setup tcp pointers*/
710 /*setup tcp control variables*/
720 /*One byte options (no length)*/
727 /*Ack Vector Option*/
728 if(*opt==38 || *opt==39){
731 /*loop through Vector*/
733 /*ack vector works BACKWARDS through time*/
735 if((*cur & 0xC0)==0xC0 || (*cur & 0xC0)==0x40){ //lost packet
736 if(cont){ /*end a SACK run, if one is started*/
737 bR=convert_ack(seq, bp);
747 bp= bp - (*cur & 0x3F)- 1;
750 if((*cur & 0xC0)==0x00){ //received packet
751 if(!cont){ /*if no SACK run and we can start another one, do so*/
753 bL=convert_ack(seq, bp);
759 bp = bp -(*cur & 0x3F)- 1;
770 /*if we are in the middle of a SACK run, close it*/
772 bR=convert_ack(seq, bp);
780 /*adjust length if the option is actually added*/
788 void dbgprintf(int level, const char *fmt, ...)
793 vfprintf(stderr, fmt, args);