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>
25 2)DCCP MUST use 48 bit sequence numbers
26 3)DCCP DATA packets are not implemented (Linux doesn't use them)
27 4)DCCP Ack packets show up as TCP packets containing one byte
28 ******************************************************************************/
31 unsigned int interp_ack_vect(u_char* hdr);
32 u_int32_t initialize_seq(struct host *seq, __be32 initial);
33 u_int32_t add_new_seq(struct host *seq, __be32 num, int size, enum dccp_pkt_type type);
34 u_int32_t convert_ack(struct host *seq, __be32 num);
35 int acked_packet_size(struct host *seq, __be32 num);
36 void ack_vect2sack(struct host *seq, struct tcphdr *tcph, u_char* tcpopts, u_char* dccphdr, __be32 dccpack);
38 /*do all the dccp to tcp conversions*/
39 int ccid2_convert_packet(struct packet *new, const struct const_packet* old)
42 struct dccp_hdr *dccph;
43 struct dccp_hdr_ext *dccphex;
44 struct dccp_hdr_ack_bits *dccphack;
53 /*cast header pointers*/
54 tcph=(struct tcphdr*)new->data;
55 dccph=(struct dccp_hdr*)old->data;
56 dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
57 dccphack=(struct dccp_hdr_ack_bits*)(old->data+ sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
60 if(get_host(new->src_id, new->dest_id, new->id_len,
61 dccph->dccph_sport, dccph->dccph_dport, &h1, &h2)){
62 dbgprintf(0,"Error: Can't Get Hosts!\n");
65 if(h1==NULL || h2==NULL){
66 dbgprintf(0, "Error: Can't Get Hosts!\n");
70 /*Ensure packet is at least as large as DCCP header*/
71 if(dccph->dccph_type!=DCCP_PKT_DATA &&
72 old->length < (sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) +
73 sizeof(struct dccp_hdr_ack_bits))){
74 dbgprintf(0, "Error: DCCP Packet Too short!\n");
77 /*determine data length*/
78 datalength=old->length - dccph->dccph_doff*4;
79 pd=old->data + dccph->dccph_doff*4;
81 /*set TCP standard features*/
82 tcph->source=dccph->dccph_sport;
83 tcph->dest=dccph->dccph_dport;
88 /*Adjust TCP advertised window size*/
90 tcph->window=htons(30000);
93 /*make changes by packet type*/
94 if(dccph->dccph_type==DCCP_PKT_REQUEST){//DCCP REQUEST -->TCP SYN
95 dbgprintf(2,"Packet Type: Request\n");
98 tcph->window=htons(0);
100 tcph->ack_seq=htonl(0);
101 tcph->seq=htonl(initialize_seq(h1, ntohl(dccphex->dccph_seq_low)));
107 /* add Sack-permitted option, if relevant*/
109 tcpopt=(u_char*)(new->data + tcph->doff*4);
121 if(dccph->dccph_type==DCCP_PKT_RESPONSE){//DCCP RESPONSE-->TCP SYN,ACK
122 dbgprintf(2,"Packet Type: Response\n");
123 if(h2->state==OPEN && h1->state==INIT){
124 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
126 tcph->window=htons(0);
128 tcph->seq=htonl(initialize_seq(h1, ntohl(dccphex->dccph_seq_low)));
134 /* add Sack-permitted option, if relevant*/
136 tcpopt=(u_char*)(new->data + tcph->doff*4);
147 if(dccph->dccph_type==DCCP_PKT_DATA){//DCCP DATA----Never seen in packet capture
148 dbgprintf(0,"DCCP Data packet not yet implemented\n");
152 if(dccph->dccph_type==DCCP_PKT_DATAACK){//DCCP DATAACK-->TCP ACK with data
153 dbgprintf(2,"Packet Type: DataAck\n");
155 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
157 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
159 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),datalength, dccph->dccph_type));
161 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
164 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
165 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
175 npd=new->data + tcph->doff*4;
176 memcpy(npd, pd, datalength);
179 len= tcph->doff*4 + datalength;
182 if(dccph->dccph_type==DCCP_PKT_ACK){ //DCCP ACK -->TCP ACK with no data
183 dbgprintf(2,"Packet Type: Ack\n");
185 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
187 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
189 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
191 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*1400);
192 if(-interp_ack_vect((u_char*)dccph)*1400 > 65535){
193 printf("Note: TCP Window Overflow @ %d.%d\n", (int)old->h->ts.tv_sec, (int)old->h->ts.tv_usec);
197 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
198 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
208 len=tcph->doff*4 + 1;
211 if(dccph->dccph_type==DCCP_PKT_CLOSEREQ){//DCCP CLOSEREQ----Never seen in packet capture
212 dbgprintf(0,"DCCP CloseReq not yet implemented\n");
216 if(dccph->dccph_type==DCCP_PKT_CLOSE){//DCCP CLOSE-->TCP FIN,ACK
217 dbgprintf(2,"Packet Type: Close\n");
218 update_state(h1,CLOSE);
220 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
222 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
224 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
226 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
229 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
230 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
243 if(dccph->dccph_type==DCCP_PKT_RESET){//DCCP RESET-->TCP FIN,ACK (only seen at end of connection as CLOSE ACK)
244 if(h2->state==CLOSE){
245 update_state(h1,CLOSE);
247 dbgprintf(2,"Packet Type: Reset\n");
249 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
251 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
253 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
255 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
258 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
259 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
272 if(dccph->dccph_type==DCCP_PKT_SYNC){//DCCP SYNC
273 dbgprintf(2,"Packet Type: Sync\n");
275 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
277 tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
279 tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),0,dccph->dccph_type));
281 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
283 tcph->window=htons(0);
286 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
287 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
300 if(dccph->dccph_type==DCCP_PKT_SYNCACK){//DCCP SYNACK
301 dbgprintf(2,"Packet Type: SyncAck\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),0,dccph->dccph_type));
309 tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
311 tcph->window=htons(0);
314 if(sack!=2 || interp_ack_vect((u_char*)dccph)){
315 ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low));
328 if(dccph->dccph_type==DCCP_PKT_INVALID){//DCCP INVALID----Never seen in packet capture
329 dbgprintf(0,"Invalid DCCP Packet!!\n");
338 /*Parse Ack Vector Options
339 * Returns the Number of packets since last recorded loss*/
340 unsigned int interp_ack_vect(u_char* hdr)
342 int hdrlen=((struct dccp_hdr*)hdr)->dccph_doff*4;
343 //struct dccp_hdr_ext* e=(struct dccp_hdr_ext*)hdr + sizeof(struct dccp_hdr);
352 /*setup pointer to DCCP options and determine how long the options are*/
353 optlen=hdrlen-sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
354 opt=hdr + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
359 /*One byte options (no length)*/
366 /*Check option length*/
369 dbgprintf(0, "Warning: Option would extend into packet data\n");
373 /*Ack Vector Option*/
374 if(*opt==38 || *opt==39){
377 /*loop through Vector*/
379 /*ack vector works BACKWARDS through time*/
381 /*keep track of total packets recieved and if
382 a packet is lost, subtract all packets received
384 if((*cur & 0xC0)==0xC0 || (*cur & 0xC0)==0x40){ //lost packet
389 if((*cur & 0xC0)==0x00){ //received packet
390 bp+= (*cur & 0x3F)+1;
393 if(((*cur& 0xC0)!= 0xC0) && ((*cur& 0xC0)!= 0x00) && ((*cur& 0xC0)!= 0x40)){
394 dbgprintf(1, "Warning: Invalid Ack Vector!! (Linux will handle poorly!)\n");
405 dbgprintf(2,"Ack vector adding: %i\n", additional);
410 /* Setup Sequence Number Structure*/
411 u_int32_t initialize_seq(struct host *seq, __be32 initial)
413 /*set default values*/
418 seq->table=(struct tbl*)malloc(sizeof(struct tbl)*TBL_SZ);
419 if(seq->table==NULL){
420 dbgprintf(0,"Can't Allocate Memory!\n");
424 /*add first sequence number*/
425 seq->table[0].old=initial;
426 seq->table[0].new=initial;
427 seq->table[0].type=DCCP_PKT_REQUEST;
428 seq->table[0].size=0;
429 update_state(seq,OPEN);
434 /*Convert Sequence Numbers*/
435 u_int32_t add_new_seq(struct host *seq, __be32 num, int size, enum dccp_pkt_type type)
439 dbgprintf(0,"ERROR NULL POINTER!\n");
443 if(seq->table==NULL){
444 dbgprintf(1, "Warning: Connection uninitialized\n");
445 return initialize_seq(seq, num);
448 /*account for missing packets*/
449 if(num - seq->table[seq->cur].old +1 >=100){
450 dbgprintf(1,"Missing more than 100 packets!\n");
452 while(seq->table[seq->cur].old +1 < num && seq->table[seq->cur].old +1 > 0){
454 if(num - seq->table[seq->cur].old +1 <100){
455 dbgprintf(1,"Missing Packet: %X\n",seq->table[prev].new+1);
457 seq->cur=(seq->cur+1)%(seq->size);/*find next available table slot*/
458 seq->table[seq->cur].old=seq->table[prev].old+1;
459 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
460 seq->table[seq->cur].size=size;
461 seq->table[seq->cur].type=type;
465 seq->cur=(seq->cur+1)%(seq->size);/*find next available table slot*/
466 seq->table[seq->cur].old=num;
467 seq->table[seq->cur].size=size;
468 seq->table[seq->cur].type=type;
469 if(seq->table[prev].type==DCCP_PKT_REQUEST || seq->table[prev].type==DCCP_PKT_RESPONSE){
470 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
471 seq->table[seq->cur].size=1;
472 return seq->table[prev].new + seq->table[prev].size+1;
474 if(type==DCCP_PKT_DATA || type==DCCP_PKT_DATAACK || type==DCCP_PKT_ACK){
475 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
476 return seq->table[seq->cur].new+1;
478 if(type==DCCP_PKT_SYNC || type==DCCP_PKT_SYNCACK){
479 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
480 return seq->table[seq->cur].new;
482 seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
483 return seq->table[seq->cur].new +1;
487 /*Convert Ack Numbers*/
488 u_int32_t convert_ack(struct host *seq, __be32 num)
491 dbgprintf(0,"ERROR NULL POINTER!\n");
495 if(seq->table==NULL){
496 dbgprintf(1, "Warning: Connection uninitialized\n");
497 initialize_seq(seq, num);
500 /*loop through table looking for the DCCP ack number*/
501 for(int i=0; i < seq->size; i++){
502 if(seq->table[i].old==num){
503 return seq->table[i].new + seq->table[i].size + 1; /*TCP acks the sequence number plus 1*/
507 dbgprintf(1, "Error: Address Not Found! looking for: %X\n", num);
512 /* Get size of packet being acked*/
513 int acked_packet_size(struct host *seq, __be32 num)
516 dbgprintf(0,"ERROR NULL POINTER!\n");
520 if(seq->table==NULL){
521 dbgprintf(1, "Warning: Connection uninitialized\n");
522 initialize_seq(seq, num);
525 /*loop through table looking for the DCCP ack number*/
526 for(int i=0; i < seq->size; i++){
527 if(seq->table[i].old==num){
528 return seq->table[i].size;
532 dbgprintf(1, "Error: Address Not Found! looking for: %X\n", num);
537 /*Ack Vector to SACK Option*/
538 void ack_vect2sack(struct host *seq, struct tcphdr *tcph, u_char* tcpopts, u_char* dccphdr, __be32 dccpack)
540 int hdrlen=((struct dccp_hdr*)dccphdr)->dccph_doff*4;
557 /*setup pointer to DCCP options and determine how long the options are*/
558 optlen=hdrlen-sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
559 opt=dccphdr + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
561 /*setup tcp pointers*/
570 /*setup tcp control variables*/
579 /*One byte options (no length)*/
588 dbgprintf(0, "Warning: Option would extend into packet data\n");
592 /*Ack Vector Option*/
593 if(*opt==38 || *opt==39){
596 /*loop through Vector*/
598 /*ack vector works BACKWARDS through time*/
600 if((*cur & 0xC0)==0xC0 || (*cur & 0xC0)==0x40){ //lost packet
601 if(cont){ /*end a SACK run, if one is started*/
602 bR=convert_ack(seq, bp);
612 bp= bp - (*cur & 0x3F)- 1;
615 if((*cur & 0xC0)==0x00){ //received packet
616 if(!cont){ /*if no SACK run and we can start another one, do so*/
618 bL=convert_ack(seq, bp);
624 bp = bp -(*cur & 0x3F)- 1;
635 /*if we are in the middle of a SACK run, close it*/
637 bR=convert_ack(seq, bp);
645 /*adjust length if the option is actually added*/