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");
127 u_char *user=(u_char*)out;
128 pcap_loop(in, -1, handle_packet, user);
132 pcap_dump_close(out);
137 /*call back function for pcap_loop--do basic packet handling*/
138 void handle_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
141 struct pcap_pkthdr nh;
144 struct const_packet old;
146 /*Determine the link type for this packet*/
147 link_type=pcap_datalink(in);
149 /*create new libpcap header*/
150 memcpy(&nh, h, sizeof(struct pcap_pkthdr));
152 /*Setup packet structs*/
154 old.length=h->caplen;
157 new.length=MAX_PACKET;
159 /*create buffer for new packet*/
160 new.data=ndata=malloc(MAX_PACKET);
162 dbgprintf(0,"Error: Couldn't allocate Memory\n");
166 /*make sure the packet is all zero*/
167 memset(new.data, 0, MAX_PACKET);
169 /*do all the fancy conversions*/
170 if(!do_encap(link_type, &new, &old)){
176 pcap_dump(user,&nh, ndata);
183 /*do all the dccp to tcp conversions*/
184 int convert_packet(struct packet *new, const struct const_packet* old)
187 struct dccp_hdr *dccph;
188 struct dccp_hdr_ext *dccphex;
189 struct dccp_hdr_ack_bits *dccphack;
190 struct host *h1=NULL;
191 struct host *h2=NULL;
199 if(!new || !old || !new->data || !old->data || !new->h || !old->h){
200 dbgprintf(0,"Error: Convert Packet Function given bad data!\n");
203 if(old->length < sizeof(struct dccp_hdr) || new->length < sizeof(struct dccp_hdr)){
204 dbgprintf(0, "Error: Convert Packet Function given packet of wrong size!\n");
208 /*cast header pointers*/
209 tcph=(struct tcphdr*)new->data;
210 tcpopt=new->data + sizeof(struct tcphdr);
211 dccph=(struct dccp_hdr*)old->data;
212 dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
213 dccphack=(struct dccp_hdr_ack_bits*)(old->data+ sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
215 dbgprintf(2,"Sequence Number: %llu\n", (unsigned long long)(((unsigned long)ntohs(dccph->dccph_seq)<<32) + ntohl(dccphex->dccph_seq_low)));
218 if(get_host(new->src_id, new->dest_id, dccph->dccph_sport, dccph->dccph_dport, h1, h2)){
219 dbgprintf(0,"Error: Can't Get Hosts!\n");
223 dbgprintf(0, "Error: Can't Get Hosts!\n");
227 /*determine data length*/
228 datalength=old->length - dccph->dccph_doff*4;
229 pd=old->data + dccph->dccph_doff*4;
231 /*set TCP standard features*/
232 tcph->source=dccph->dccph_sport;
233 tcph->dest=dccph->dccph_dport;
235 tcph->check=htonl(0);
238 /*Adjust TCP advertised window size*/
240 tcph->window=htons(30000);
243 /*make changes by packet type*/
244 if(dccph->dccph_type==DCCP_PKT_REQUEST){//DCCP REQUEST -->TCP SYN
245 dbgprintf(2,"Packet Type: Request\n");
248 tcph->window=htons(0);
250 tcph->ack_seq=htonl(0);
251 tcph->seq=htonl(initialize_seq(h1, dccph->dccph_sport, ntohl(dccphex->dccph_seq_low)));
257 /* add Sack-permitted option, if relevant*/
270 if(dccph->dccph_type==DCCP_PKT_RESPONSE){//DCCP RESPONSE-->TCP SYN,ACK
271 dbgprintf(2,"Packet Type: Response\n");
272 if(h2->state==OPEN && h1->state==INIT){
273 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
275 tcph->window=htons(0);
277 tcph->seq=htonl(initialize_seq(h1, dccph->dccph_sport, ntohl(dccphex->dccph_seq_low)));
283 /* add Sack-permitted option, if relevant*/
295 if(dccph->dccph_type==DCCP_PKT_DATA){//DCCP DATA----Never seen in packet capture
296 dbgprintf(0,"DCCP Data packet not yet implemented\n");
300 if(dccph->dccph_type==DCCP_PKT_DATAACK){//DCCP DATAACK-->TCP ACK with data
301 dbgprintf(2,"Packet Type: DataAck\n");
303 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
305 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
307 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),datalength, dccph->dccph_type));
309 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
312 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
313 ack_vect2sack(h2, tcph, tcpopt, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
323 npd=new->data + tcph->doff*4;
324 memcpy(npd, pd, datalength);
327 len= tcph->doff*4 + datalength;
330 if(dccph->dccph_type==DCCP_PKT_ACK){ //DCCP ACK -->TCP ACK with no data
331 dbgprintf(2,"Packet Type: Ack\n");
333 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
335 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
337 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
339 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*1400);
340 if(-interp_ack_vect((u_char*)dccph)*1400 > 65535){
341 printf("Note: TCP Window Overflow @ %d.%d\n", (int)old->h->ts.tv_sec, (int)old->h->ts.tv_usec);
345 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
346 ack_vect2sack(h2, tcph, tcpopt, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
356 len=tcph->doff*4 + 1;
359 if(dccph->dccph_type==DCCP_PKT_CLOSEREQ){//DCCP CLOSEREQ----Never seen in packet capture
360 dbgprintf(0,"DCCP CloseReq not yet implemented\n");
364 if(dccph->dccph_type==DCCP_PKT_CLOSE){//DCCP CLOSE-->TCP FIN,ACK
365 dbgprintf(2,"Packet Type: Close\n");
366 update_state(h1,CLOSE);
368 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
370 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
372 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
374 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
377 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
378 ack_vect2sack(h2, tcph, tcpopt, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
391 if(dccph->dccph_type==DCCP_PKT_RESET){//DCCP RESET-->TCP FIN,ACK (only seen at end of connection as CLOSE ACK)
392 if(h2->state==CLOSE){
393 update_state(h1,CLOSE);
395 dbgprintf(2,"Packet Type: Reset\n");
397 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
399 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
401 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
403 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
406 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
407 ack_vect2sack(h2, tcph, tcpopt, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
420 if(dccph->dccph_type==DCCP_PKT_SYNC){//DCCP SYNC
421 dbgprintf(2,"Packet Type: Sync\n");
423 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
425 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
427 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),0,dccph->dccph_type));
429 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
431 tcph->window=htons(0);
434 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
435 ack_vect2sack(h2, tcph, tcpopt, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
448 if(dccph->dccph_type==DCCP_PKT_SYNCACK){//DCCP SYNACK
449 dbgprintf(2,"Packet Type: SyncAck\n");
451 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
453 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
455 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),0,dccph->dccph_type));
457 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
459 tcph->window=htons(0);
462 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
463 ack_vect2sack(h2, tcph, tcpopt, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low));
476 if(dccph->dccph_type==DCCP_PKT_INVALID){//DCCP INVALID----Never seen in packet capture
477 dbgprintf(0,"Invalid DCCP Packet!!\n");
486 /*Parse Ack Vector Options
487 * Returns the Number of packets since last recorded loss*/
488 unsigned int interp_ack_vect(u_char* hdr)
490 int hdrlen=((struct dccp_hdr*)hdr)->dccph_doff*4;
491 //struct dccp_hdr_ext* e=(struct dccp_hdr_ext*)hdr + sizeof(struct dccp_hdr);
500 /*setup pointer to DCCP options and determine how long the options are*/
501 optlen=hdrlen-sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
502 opt=hdr + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
508 /*One byte options (no length)*/
515 /*Ack Vector Option*/
516 if(*opt==38 || *opt==39){
519 /*loop through Vector*/
521 /*ack vector works BACKWARDS through time*/
523 /*keep track of total packets recieved and if
524 a packet is lost, subtract all packets received
526 if((*cur & 0xC0)==0xC0 || (*cur & 0xC0)==0x40){ //lost packet
531 if((*cur & 0xC0)==0x00){ //received packet
532 bp+= (*cur & 0x3F)+1;
535 if(((*cur& 0xF0)!= 0xC0) && ((*cur& 0xF0)!= 0x00) && ((*cur& 0xF0)!= 0x40)){
536 dbgprintf(1, "Warning: Invalid Ack Vector!! (Linux will handle poorly!)\n");
547 dbgprintf(2,"Ack vector adding: %i\n", additional);
552 /* Setup Sequence Number Structure*/
553 u_int32_t initialize_seq(struct host *seq, __be16 source, __be32 initial)
555 /*set default values*/
560 seq->table=(struct tbl*)malloc(sizeof(struct tbl)*TBL_SZ);
561 if(seq->table==NULL){
562 dbgprintf(0,"Can't Allocate Memory!\n");
566 /*add first sequence number*/
567 seq->table[0].old=initial;
568 seq->table[0].new=initial;
569 seq->table[0].type=DCCP_PKT_REQUEST;
570 seq->table[0].size=0;
571 update_state(seq,OPEN);
576 /*Convert Sequence Numbers*/
577 u_int32_t add_new_seq(struct host *seq, __be32 num, int size, enum dccp_pkt_type type)
581 dbgprintf(0,"ERROR NULL POINTER!\n");
585 /*account for missing packets*/
586 while(seq->table[seq->cur].old +1 < num && seq->table[seq->cur].old +1 > 0){
588 dbgprintf(1,"Missing Packet: %X\n",seq->table[prev].new+1);
589 seq->cur=(seq->cur+1)%(seq->size);/*find next available table slot*/
590 seq->table[seq->cur].old=seq->table[prev].old+1;
591 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
592 seq->table[seq->cur].size=size;
593 seq->table[seq->cur].type=type;
597 seq->cur=(seq->cur+1)%(seq->size);/*find next available table slot*/
598 seq->table[seq->cur].old=num;
599 seq->table[seq->cur].size=size;
600 seq->table[seq->cur].type=type;
601 if(seq->table[prev].type==DCCP_PKT_REQUEST || seq->table[prev].type==DCCP_PKT_RESPONSE){
602 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
603 seq->table[seq->cur].size=1;
604 return seq->table[prev].new + seq->table[prev].size+1;
606 if(type==DCCP_PKT_DATA || type==DCCP_PKT_DATAACK || type==DCCP_PKT_ACK){
607 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
608 return seq->table[seq->cur].new+1;
610 if(type==DCCP_PKT_SYNC || type==DCCP_PKT_SYNCACK){
611 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
612 return seq->table[seq->cur].new;
614 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
615 return seq->table[seq->cur].new +1;
619 /*Convert Ack Numbers*/
620 u_int32_t convert_ack(struct host *seq, __be32 num)
623 dbgprintf(0,"ERROR NULL POINTER!\n");
627 /*loop through table looking for the DCCP ack number*/
628 for(int i=0; i < seq->size; i++){
629 if(seq->table[i].old==num){
630 return seq->table[i].new + seq->table[i].size + 1; /*TCP acks the sequence number plus 1*/
634 dbgprintf(1, "Error: Address Not Found! looking for: %X\n", num);
639 /* Get size of packet being acked*/
640 int acked_packet_size(struct host *seq, __be32 num)
643 dbgprintf(0,"ERROR NULL POINTER!\n");
647 /*loop through table looking for the DCCP ack number*/
648 for(int i=0; i < seq->size; i++){
649 if(seq->table[i].old==num){
650 return seq->table[i].size;
654 dbgprintf(1, "Error: Address Not Found! looking for: %X\n", num);
659 /*Ack Vector to SACK Option*/
660 void ack_vect2sack(struct host *seq, struct tcphdr *tcph, u_char* tcpopts, u_char* dccphdr, __be32 dccpack)
662 int hdrlen=((struct dccp_hdr*)dccphdr)->dccph_doff*4;
679 /*setup pointer to DCCP options and determine how long the options are*/
680 optlen=hdrlen-sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
681 opt=dccphdr + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
683 /*setup tcp pointers*/
692 /*setup tcp control variables*/
702 /*One byte options (no length)*/
709 /*Ack Vector Option*/
710 if(*opt==38 || *opt==39){
713 /*loop through Vector*/
715 /*ack vector works BACKWARDS through time*/
717 if((*cur & 0xC0)==0xC0 || (*cur & 0xC0)==0x40){ //lost packet
718 if(cont){ /*end a SACK run, if one is started*/
719 bR=convert_ack(seq, bp);
729 bp= bp - (*cur & 0x3F)- 1;
732 if((*cur & 0xC0)==0x00){ //received packet
733 if(!cont){ /*if no SACK run and we can start another one, do so*/
735 bL=convert_ack(seq, bp);
741 bp = bp -(*cur & 0x3F)- 1;
752 /*if we are in the middle of a SACK run, close it*/
754 bR=convert_ack(seq, bp);
762 /*adjust length if the option is actually added*/
770 void dbgprintf(int level, const char *fmt, ...)
775 vfprintf(stderr, fmt, args);