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, __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) + sizeof(struct dccp_hdr_ext)) || new->length < sizeof(struct dccp_hdr)){
206 dbgprintf(0, "Error: DCCP Packet Too short!\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 /*Ensure packet is at least as large as DCCP header*/
229 if(old->length < dccph->dccph_doff*4){
230 dbgprintf(0, "Error: DCCP Header truncated\n");
233 if(dccph->dccph_type!=DCCP_PKT_DATA &&
234 old->length < (sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) +
235 sizeof(struct dccp_hdr_ack_bits))){
236 dbgprintf(0, "Error: DCCP Packet Too short!\n");
239 /*determine data length*/
240 datalength=old->length - dccph->dccph_doff*4;
241 pd=old->data + dccph->dccph_doff*4;
243 /*set TCP standard features*/
244 tcph->source=dccph->dccph_sport;
245 tcph->dest=dccph->dccph_dport;
247 tcph->check=htonl(0);
250 /*Adjust TCP advertised window size*/
252 tcph->window=htons(30000);
255 /*make changes by packet type*/
256 if(dccph->dccph_type==DCCP_PKT_REQUEST){//DCCP REQUEST -->TCP SYN
257 dbgprintf(2,"Packet Type: Request\n");
260 tcph->window=htons(0);
262 tcph->ack_seq=htonl(0);
263 tcph->seq=htonl(initialize_seq(h1, ntohl(dccphex->dccph_seq_low)));
269 /* add Sack-permitted option, if relevant*/
271 tcpopt=(u_char*)(new->data + tcph->doff*4);
283 if(dccph->dccph_type==DCCP_PKT_RESPONSE){//DCCP RESPONSE-->TCP SYN,ACK
284 dbgprintf(2,"Packet Type: Response\n");
285 if(h2->state==OPEN && h1->state==INIT){
286 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
288 tcph->window=htons(0);
290 tcph->seq=htonl(initialize_seq(h1, ntohl(dccphex->dccph_seq_low)));
296 /* add Sack-permitted option, if relevant*/
298 tcpopt=(u_char*)(new->data + tcph->doff*4);
309 if(dccph->dccph_type==DCCP_PKT_DATA){//DCCP DATA----Never seen in packet capture
310 dbgprintf(0,"DCCP Data packet not yet implemented\n");
314 if(dccph->dccph_type==DCCP_PKT_DATAACK){//DCCP DATAACK-->TCP ACK with data
315 dbgprintf(2,"Packet Type: DataAck\n");
317 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
319 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
321 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),datalength, dccph->dccph_type));
323 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
326 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
327 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
337 npd=new->data + tcph->doff*4;
338 memcpy(npd, pd, datalength);
341 len= tcph->doff*4 + datalength;
344 if(dccph->dccph_type==DCCP_PKT_ACK){ //DCCP ACK -->TCP ACK with no data
345 dbgprintf(2,"Packet Type: Ack\n");
347 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
349 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
351 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
353 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*1400);
354 if(-interp_ack_vect((u_char*)dccph)*1400 > 65535){
355 printf("Note: TCP Window Overflow @ %d.%d\n", (int)old->h->ts.tv_sec, (int)old->h->ts.tv_usec);
359 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
360 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
370 len=tcph->doff*4 + 1;
373 if(dccph->dccph_type==DCCP_PKT_CLOSEREQ){//DCCP CLOSEREQ----Never seen in packet capture
374 dbgprintf(0,"DCCP CloseReq not yet implemented\n");
378 if(dccph->dccph_type==DCCP_PKT_CLOSE){//DCCP CLOSE-->TCP FIN,ACK
379 dbgprintf(2,"Packet Type: Close\n");
380 update_state(h1,CLOSE);
382 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
384 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
386 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
388 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
391 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
392 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
405 if(dccph->dccph_type==DCCP_PKT_RESET){//DCCP RESET-->TCP FIN,ACK (only seen at end of connection as CLOSE ACK)
406 if(h2->state==CLOSE){
407 update_state(h1,CLOSE);
409 dbgprintf(2,"Packet Type: Reset\n");
411 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
413 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
415 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
417 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
420 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
421 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
434 if(dccph->dccph_type==DCCP_PKT_SYNC){//DCCP SYNC
435 dbgprintf(2,"Packet Type: Sync\n");
437 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
439 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
441 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),0,dccph->dccph_type));
443 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
445 tcph->window=htons(0);
448 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
449 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
462 if(dccph->dccph_type==DCCP_PKT_SYNCACK){//DCCP SYNACK
463 dbgprintf(2,"Packet Type: SyncAck\n");
465 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
467 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
469 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),0,dccph->dccph_type));
471 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
473 tcph->window=htons(0);
476 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
477 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low));
490 if(dccph->dccph_type==DCCP_PKT_INVALID){//DCCP INVALID----Never seen in packet capture
491 dbgprintf(0,"Invalid DCCP Packet!!\n");
500 /*Parse Ack Vector Options
501 * Returns the Number of packets since last recorded loss*/
502 unsigned int interp_ack_vect(u_char* hdr)
504 int hdrlen=((struct dccp_hdr*)hdr)->dccph_doff*4;
505 //struct dccp_hdr_ext* e=(struct dccp_hdr_ext*)hdr + sizeof(struct dccp_hdr);
514 /*setup pointer to DCCP options and determine how long the options are*/
515 optlen=hdrlen-sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
516 opt=hdr + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
521 /*One byte options (no length)*/
528 /*Check option length*/
531 dbgprintf(0, "Warning: Option would extend into packet data\n");
535 /*Ack Vector Option*/
536 if(*opt==38 || *opt==39){
539 /*loop through Vector*/
541 /*ack vector works BACKWARDS through time*/
543 /*keep track of total packets recieved and if
544 a packet is lost, subtract all packets received
546 if((*cur & 0xC0)==0xC0 || (*cur & 0xC0)==0x40){ //lost packet
551 if((*cur & 0xC0)==0x00){ //received packet
552 bp+= (*cur & 0x3F)+1;
555 if(((*cur& 0xC0)!= 0xC0) && ((*cur& 0xC0)!= 0x00) && ((*cur& 0xC0)!= 0x40)){
556 dbgprintf(1, "Warning: Invalid Ack Vector!! (Linux will handle poorly!)\n");
567 dbgprintf(2,"Ack vector adding: %i\n", additional);
572 /* Setup Sequence Number Structure*/
573 u_int32_t initialize_seq(struct host *seq, __be32 initial)
575 /*set default values*/
580 seq->table=(struct tbl*)malloc(sizeof(struct tbl)*TBL_SZ);
581 if(seq->table==NULL){
582 dbgprintf(0,"Can't Allocate Memory!\n");
586 /*add first sequence number*/
587 seq->table[0].old=initial;
588 seq->table[0].new=initial;
589 seq->table[0].type=DCCP_PKT_REQUEST;
590 seq->table[0].size=0;
591 update_state(seq,OPEN);
596 /*Convert Sequence Numbers*/
597 u_int32_t add_new_seq(struct host *seq, __be32 num, int size, enum dccp_pkt_type type)
601 dbgprintf(0,"ERROR NULL POINTER!\n");
605 if(seq->table==NULL){
606 dbgprintf(1, "Warning: Connection uninitialized\n");
607 return initialize_seq(seq, num);
610 /*account for missing packets*/
611 while(seq->table[seq->cur].old +1 < num && seq->table[seq->cur].old +1 > 0){
613 dbgprintf(1,"Missing Packet: %X\n",seq->table[prev].new+1);
614 seq->cur=(seq->cur+1)%(seq->size);/*find next available table slot*/
615 seq->table[seq->cur].old=seq->table[prev].old+1;
616 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
617 seq->table[seq->cur].size=size;
618 seq->table[seq->cur].type=type;
622 seq->cur=(seq->cur+1)%(seq->size);/*find next available table slot*/
623 seq->table[seq->cur].old=num;
624 seq->table[seq->cur].size=size;
625 seq->table[seq->cur].type=type;
626 if(seq->table[prev].type==DCCP_PKT_REQUEST || seq->table[prev].type==DCCP_PKT_RESPONSE){
627 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
628 seq->table[seq->cur].size=1;
629 return seq->table[prev].new + seq->table[prev].size+1;
631 if(type==DCCP_PKT_DATA || type==DCCP_PKT_DATAACK || type==DCCP_PKT_ACK){
632 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
633 return seq->table[seq->cur].new+1;
635 if(type==DCCP_PKT_SYNC || type==DCCP_PKT_SYNCACK){
636 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
637 return seq->table[seq->cur].new;
639 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
640 return seq->table[seq->cur].new +1;
644 /*Convert Ack Numbers*/
645 u_int32_t convert_ack(struct host *seq, __be32 num)
648 dbgprintf(0,"ERROR NULL POINTER!\n");
652 if(seq->table==NULL){
653 dbgprintf(1, "Warning: Connection uninitialized\n");
654 initialize_seq(seq, num);
657 /*loop through table looking for the DCCP ack number*/
658 for(int i=0; i < seq->size; i++){
659 if(seq->table[i].old==num){
660 return seq->table[i].new + seq->table[i].size + 1; /*TCP acks the sequence number plus 1*/
664 dbgprintf(1, "Error: Address Not Found! looking for: %X\n", num);
669 /* Get size of packet being acked*/
670 int acked_packet_size(struct host *seq, __be32 num)
673 dbgprintf(0,"ERROR NULL POINTER!\n");
677 if(seq->table==NULL){
678 dbgprintf(1, "Warning: Connection uninitialized\n");
679 initialize_seq(seq, num);
682 /*loop through table looking for the DCCP ack number*/
683 for(int i=0; i < seq->size; i++){
684 if(seq->table[i].old==num){
685 return seq->table[i].size;
689 dbgprintf(1, "Error: Address Not Found! looking for: %X\n", num);
694 /*Ack Vector to SACK Option*/
695 void ack_vect2sack(struct host *seq, struct tcphdr *tcph, u_char* tcpopts, u_char* dccphdr, __be32 dccpack)
697 int hdrlen=((struct dccp_hdr*)dccphdr)->dccph_doff*4;
714 /*setup pointer to DCCP options and determine how long the options are*/
715 optlen=hdrlen-sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
716 opt=dccphdr + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
718 /*setup tcp pointers*/
727 /*setup tcp control variables*/
736 /*One byte options (no length)*/
745 dbgprintf(0, "Warning: Option would extend into packet data\n");
749 /*Ack Vector Option*/
750 if(*opt==38 || *opt==39){
753 /*loop through Vector*/
755 /*ack vector works BACKWARDS through time*/
757 if((*cur & 0xC0)==0xC0 || (*cur & 0xC0)==0x40){ //lost packet
758 if(cont){ /*end a SACK run, if one is started*/
759 bR=convert_ack(seq, bp);
769 bp= bp - (*cur & 0x3F)- 1;
772 if((*cur & 0xC0)==0x00){ //received packet
773 if(!cont){ /*if no SACK run and we can start another one, do so*/
775 bL=convert_ack(seq, bp);
781 bp = bp -(*cur & 0x3F)- 1;
792 /*if we are in the middle of a SACK run, close it*/
794 bR=convert_ack(seq, bp);
802 /*adjust length if the option is actually added*/
810 void dbgprintf(int level, const char *fmt, ...)
815 vfprintf(stderr, fmt, args);