/******************************************************************************
Author: Samuel Jero
-Date: 1/2011
+Date: 11/2011
Description: Program to convert a DCCP flow to a TCP flow for DCCP analysis via
tcptrace.
Notes:
- 1)Supports only a single DCCP contection per capture
- 2)Source Port!=Destination Port
- 3)DCCP MUST use 48 bit sequence numbers
- 4)Checksums are not computed (they are zeroed)
- 5)Only implements those packet types normally used in a session
- 6)DCCP Ack packets show up as TCP packets containing one byte
- 7)Very little error checking of packet headers
+ 1)CCID2 ONLY
+ 2)DCCP MUST use 48 bit sequence numbers
+ 3)Checksums are not computed (they are zeroed)
+ 4)DCCP DATA packets are not implemented (Linux doesn't use them)
+ 5)DCCP Ack packets show up as TCP packets containing one byte
******************************************************************************/
#include "dccp2tcp.h"
int green=0; /*tcptrace green line as currently acked packet*/
int sack=0; /*add TCP SACKS*/
-pcap_t* in; /*libpcap input file discriptor*/
-pcap_dumper_t *out; /*libpcap output file discriptor*/
-struct seq_num *s1; /*sequence number structure for side one of connection*/
-struct seq_num *s2; /*sequence number structure for side two of connection*/
+pcap_t* in; /*libpcap input file discriptor*/
+pcap_dumper_t *out; /*libpcap output file discriptor*/
+struct connection *chead; /*connection list*/
void PcapSavePacket(struct pcap_pkthdr *h, u_char *data);
void process_packets();
void handle_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes);
-void convert_packet(struct pcap_pkthdr *h, const u_char *odata, u_char *ndata);
+int convert_packet(struct packet *new, const struct const_packet* old);
unsigned int interp_ack_vect(u_char* hdr);
-u_int32_t initialize_seq(struct seq_num **seq, __be16 source, __be32 initial);
-u_int32_t add_new_seq(struct seq_num *seq, __be32 num, int ack);
-u_int32_t convert_ack(struct seq_num *seq, __be32 num);
-int acked_packet_size(struct seq_num *seq, __be32 num);
-void ack_vect2sack(struct seq_num *seq, struct tcphdr *tcph, u_char* tcpopts, u_char* dccphdr, __be32 dccpack);
+u_int32_t initialize_seq(struct host *seq, __be32 initial);
+u_int32_t add_new_seq(struct host *seq, __be32 num, int size, enum dccp_pkt_type type);
+u_int32_t convert_ack(struct host *seq, __be32 num);
+int acked_packet_size(struct host *seq, __be32 num);
+void ack_vect2sack(struct host *seq, struct tcphdr *tcph, u_char* tcpopts, u_char* dccphdr, __be32 dccpack);
/*Parse commandline options and open files*/
/*loop through commandline options*/
for(int i=1; i < argc; i++){
- if(argv[i][0]!='-'){
- if(dfile==NULL){ /*assign first non-dash argument to the dccp file*/
+ if(argv[i][0]!='-' || (argv[i][0]=='-' && strlen(argv[i])==1)){
+ if(dfile==NULL || argv[i][0]=='-'){
+ /*assign first non-dash (or only dash) argument to the dccp file*/
dfile=argv[i];
}else{
if(tfile==NULL){
green=1;
}
if(argv[i][1]=='s' && strlen(argv[i])==2){ /*sack option*/
- sack=1;
+ sack++;
}
}
}
}
/*process packets*/
+ chead=NULL;
u_char *user=(u_char*)out;
pcap_loop(in, -1, handle_packet, user);
/*close files*/
pcap_close(in);
pcap_dump_close(out);
+
+ /*Delete all connections*/
+ cleanup_connections();
return 0;
}
/*call back function for pcap_loop--do basic packet handling*/
void handle_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
{
- u_char *ndata;
- struct pcap_pkthdr nh;
+ u_char *ndata;
+ struct pcap_pkthdr nh;
+ int link_type;
+ struct packet new;
+ struct const_packet old;
+
+ /*Determine the link type for this packet*/
+ link_type=pcap_datalink(in);
/*create new libpcap header*/
memcpy(&nh, h, sizeof(struct pcap_pkthdr));
+ /*Setup packet structs*/
+ old.h=h;
+ old.length=h->caplen;
+ old.data=bytes;
+ new.h=&nh;
+ new.length=MAX_PACKET;
+
/*create buffer for new packet*/
- ndata=malloc(MAX_PACKET);
+ new.data=ndata=malloc(MAX_PACKET);
if(ndata==NULL){
dbgprintf(0,"Error: Couldn't allocate Memory\n");
exit(1);
}
/*make sure the packet is all zero*/
- memset(ndata, 0, MAX_PACKET);
+ memset(new.data, 0, MAX_PACKET);
/*do all the fancy conversions*/
- convert_packet(&nh, bytes, ndata);
+ if(!do_encap(link_type, &new, &old)){
+ free(ndata);
+ return;
+ }
/*save packet*/
pcap_dump(user,&nh, ndata);
/*do all the dccp to tcp conversions*/
-void convert_packet(struct pcap_pkthdr *h, const u_char *odata, u_char *ndata)
+int convert_packet(struct packet *new, const struct const_packet* old)
{
- u_char* ncur=ndata;
- const u_char* ocur=odata;
- int length=h->caplen;
- struct iphdr *iph;
- struct tcphdr *tcph;
- struct dccp_hdr *dccph;
- struct dccp_hdr_ext *dccphex;
- struct dccp_hdr_ack_bits *dccphack;
- int datalength;
- const u_char* pd;
- u_char* npd;
- u_char* tcpopt;
-
- /*copy ethernet and ip headers over*/
- memcpy(ncur, ocur, sizeof(struct ether_header)+sizeof(struct iphdr) );
- ocur+=sizeof(struct ether_header)+ sizeof(struct iphdr);
- ncur+=sizeof(struct ether_header) +sizeof(struct iphdr);
- length-=sizeof(struct ether_header) +sizeof(struct iphdr);
-
- /*set ip to indicate that tcp is next protocol*/
- iph= (struct iphdr *) (ncur - sizeof(struct iphdr));
- iph->protocol=6;
- iph->check=htonl(0);
+ struct tcphdr *tcph;
+ struct dccp_hdr *dccph;
+ struct dccp_hdr_ext *dccphex;
+ struct dccp_hdr_ack_bits *dccphack;
+ struct host *h1=NULL;
+ struct host *h2=NULL;
+ int datalength;
+ int len=0;
+ const u_char* pd;
+ u_char* npd;
+ u_char* tcpopt;
+
+ /*Safety checks*/
+ if(!new || !old || !new->data || !old->data || !new->h || !old->h){
+ dbgprintf(0,"Error: Convert Packet Function given bad data!\n");
+ exit(1);
+ return 0;
+ }
+ if(old->length < (sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext)) || new->length < sizeof(struct dccp_hdr)){
+ dbgprintf(0, "Error: DCCP Packet Too short!\n");
+ return 0;
+ }
/*cast header pointers*/
- tcph=(struct tcphdr*)ncur;
- tcpopt=ncur+ sizeof(struct tcphdr);
- dccph=(struct dccp_hdr*)ocur;
- dccphex=(struct dccp_hdr_ext*)(ocur+sizeof(struct dccp_hdr));
- dccphack=(struct dccp_hdr_ack_bits*)(ocur+ sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
+ tcph=(struct tcphdr*)new->data;
+ dccph=(struct dccp_hdr*)old->data;
+ dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
+ dccphack=(struct dccp_hdr_ack_bits*)(old->data+ sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext));
dbgprintf(2,"Sequence Number: %llu\n", (unsigned long long)(((unsigned long)ntohs(dccph->dccph_seq)<<32) + ntohl(dccphex->dccph_seq_low)));
+ /*Get Hosts*/
+ if(get_host(new->src_id, new->dest_id, dccph->dccph_sport, dccph->dccph_dport, &h1, &h2)){
+ dbgprintf(0,"Error: Can't Get Hosts!\n");
+ return 0;
+ }
+ if(h1==NULL || h2==NULL){
+ dbgprintf(0, "Error: Can't Get Hosts!\n");
+ return 0;
+ }
+
+ /*Ensure packet is at least as large as DCCP header*/
+ if(old->length < dccph->dccph_doff*4){
+ dbgprintf(0, "Error: DCCP Header truncated\n");
+ return 0;
+ }
+ if(dccph->dccph_type!=DCCP_PKT_DATA &&
+ old->length < (sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) +
+ sizeof(struct dccp_hdr_ack_bits))){
+ dbgprintf(0, "Error: DCCP Packet Too short!\n");
+ }
+
/*determine data length*/
- datalength=ntohs(iph->tot_len) - sizeof(struct iphdr) - dccph->dccph_doff*4;
- pd=odata + sizeof(struct ether_header)+sizeof(struct iphdr) + dccph->dccph_doff*4;
+ datalength=old->length - dccph->dccph_doff*4;
+ pd=old->data + dccph->dccph_doff*4;
- /*set tcp standard features*/
+ /*set TCP standard features*/
tcph->source=dccph->dccph_sport;
tcph->dest=dccph->dccph_dport;
tcph->doff=5;
/*make changes by packet type*/
if(dccph->dccph_type==DCCP_PKT_REQUEST){//DCCP REQUEST -->TCP SYN
dbgprintf(2,"Packet Type: Request\n");
+ if(h1->state==INIT){
+ if(yellow){
+ tcph->window=htons(0);
+ }
+ tcph->ack_seq=htonl(0);
+ tcph->seq=htonl(initialize_seq(h1, ntohl(dccphex->dccph_seq_low)));
+ tcph->syn=1;
+ tcph->ack=0;
+ tcph->fin=0;
+ tcph->rst=0;
- if(yellow){
- tcph->window=htons(0);
- }
- tcph->ack_seq=htonl(0);
- tcph->seq=htonl(initialize_seq(&s1, dccph->dccph_sport, ntohl(dccphex->dccph_seq_low)));
- tcph->syn=1;
- tcph->ack=0;
- tcph->fin=0;
- tcph->rst=0;
+ /* add Sack-permitted option, if relevant*/
+ if(sack){
+ tcpopt=(u_char*)(new->data + tcph->doff*4);
+ *tcpopt=4;
+ tcpopt++;
+ *tcpopt=2;
+ tcph->doff++;
+ }
- /* add Sack-permitted option, if relevant*/
- if(sack){
- *tcpopt=4;
- tcpopt++;
- *tcpopt=2;
- tcph->doff++;
+ /*calculate length*/
+ len=tcph->doff*4;
}
-
- /*set libpcap header lengths*/
- h->len=sizeof(struct ether_header) + sizeof(struct iphdr) + tcph->doff*4;
- h->caplen=sizeof(struct ether_header) + sizeof(struct iphdr) + tcph->doff*4;
-
- /*set length in ip header*/
- iph->tot_len=htons(sizeof(struct iphdr) + tcph->doff*4);
}
if(dccph->dccph_type==DCCP_PKT_RESPONSE){//DCCP RESPONSE-->TCP SYN,ACK
dbgprintf(2,"Packet Type: Response\n");
- tcph->ack_seq=htonl(convert_ack(s1,ntohl(dccphack->dccph_ack_nr_low)));
- if(yellow){
- tcph->window=htons(0);
- }
- tcph->seq=htonl(initialize_seq(&s2, dccph->dccph_sport, ntohl(dccphex->dccph_seq_low)));
- tcph->syn=1;
- tcph->ack=1;
- tcph->fin=0;
- tcph->rst=0;
-
- /* add Sack-permitted option, if relevant*/
- if(sack){
- *tcpopt=4;
- *(tcpopt+1)=2;
- tcph->doff++;
- }
+ if(h2->state==OPEN && h1->state==INIT){
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
+ if(yellow){
+ tcph->window=htons(0);
+ }
+ tcph->seq=htonl(initialize_seq(h1, ntohl(dccphex->dccph_seq_low)));
+ tcph->syn=1;
+ tcph->ack=1;
+ tcph->fin=0;
+ tcph->rst=0;
- /*set libpcap header lengths*/
- h->len=sizeof(struct ether_header) + sizeof(struct iphdr) + tcph->doff*4;
- h->caplen=sizeof(struct ether_header) + sizeof(struct iphdr) + tcph->doff*4;
+ /* add Sack-permitted option, if relevant*/
+ if(sack){
+ tcpopt=(u_char*)(new->data + tcph->doff*4);
+ *tcpopt=4;
+ *(tcpopt+1)=2;
+ tcph->doff++;
+ }
- /*set length in ip header*/
- iph->tot_len=htons(sizeof(struct iphdr) + tcph->doff*4);
+ /*calculate length*/
+ len=tcph->doff*4;
+ }
}
if(dccph->dccph_type==DCCP_PKT_DATA){//DCCP DATA----Never seen in packet capture
if(dccph->dccph_type==DCCP_PKT_DATAACK){//DCCP DATAACK-->TCP ACK with data
dbgprintf(2,"Packet Type: DataAck\n");
- if(s1 && dccph->dccph_sport==s1->addr){ //determine which side of connection is sending this packet
- if(green){
- tcph->ack_seq=htonl(convert_ack(s2,ntohl(dccphack->dccph_ack_nr_low)));
- }else{
- tcph->ack_seq=htonl(convert_ack(s2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
- }
- tcph->seq=htonl(add_new_seq(s1, ntohl(dccphex->dccph_seq_low),datalength));
- if(yellow){
- tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(s2, ntohl(dccphack->dccph_ack_nr_low)));
- }
- if(sack){
- ack_vect2sack(s2, tcph, tcpopt, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
- }
+ if(green){
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
}else{
- if(green){
- tcph->ack_seq=htonl(convert_ack(s1,ntohl(dccphack->dccph_ack_nr_low)));
- }else{
- tcph->ack_seq=htonl(convert_ack(s1,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
- }
- tcph->seq=htonl(add_new_seq(s2, ntohl(dccphex->dccph_seq_low),datalength));
- if(yellow){
- tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(s1, ntohl(dccphack->dccph_ack_nr_low)));
- }
- if(sack){
- ack_vect2sack(s2, tcph, tcpopt, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
+ }
+ tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),datalength, dccph->dccph_type));
+ if(yellow){
+ tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
+ }
+ if(sack){
+ if(sack!=2 || interp_ack_vect((u_char*)dccph)){
+ ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
}
}
tcph->rst=0;
/*copy data*/
- npd=ndata+ sizeof(struct ether_header)+sizeof(struct iphdr)+ tcph->doff*4;
+ npd=new->data + tcph->doff*4;
memcpy(npd, pd, datalength);
- /*set libpcap header lengths*/
- h->len=sizeof(struct ether_header) + sizeof(struct iphdr) + tcph->doff*4 + datalength;
- h->caplen=sizeof(struct ether_header) + sizeof(struct iphdr) + tcph->doff*4 + datalength;
-
- /*set length in ip header*/
- iph->tot_len=htons(sizeof(struct iphdr) + sizeof(struct tcphdr) + datalength);
+ /*calculate length*/
+ len= tcph->doff*4 + datalength;
}
if(dccph->dccph_type==DCCP_PKT_ACK){ //DCCP ACK -->TCP ACK with no data
dbgprintf(2,"Packet Type: Ack\n");
- if(s1 && dccph->dccph_sport==s1->addr){//determine which side of connection is sending this packet
- if(green){
- tcph->ack_seq=htonl(convert_ack(s2,ntohl(dccphack->dccph_ack_nr_low)));
- }else{
- tcph->ack_seq=htonl(convert_ack(s2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
- }
- tcph->seq=htonl(add_new_seq(s1, ntohl(dccphex->dccph_seq_low),1));
- if(yellow){
- tcph->window=htons(-interp_ack_vect((u_char*)dccph)*1400);
- if(-interp_ack_vect((u_char*)dccph)*1400 > 65535){
- printf("Note: TCP Window Overflow @ %d.%d\n", (int)h->ts.tv_sec, (int)h->ts.tv_usec);
- }
- }
- if(sack){
- ack_vect2sack(s2, tcph, tcpopt, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
- }
+ if(green){
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
}else{
- if(green){
- tcph->ack_seq=htonl(convert_ack(s1,ntohl(dccphack->dccph_ack_nr_low)));
- }else{
- tcph->ack_seq=htonl(convert_ack(s1,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
- }
- tcph->seq=htonl(add_new_seq(s2, ntohl(dccphex->dccph_seq_low),1));
- if(yellow){
- tcph->window=htons(-interp_ack_vect((u_char*)dccph)*1400);
- if(-interp_ack_vect((u_char*)dccph)*1400 > 65535){
- printf("Note: TCP Window Overflow @ %d.%d\n", (int)h->ts.tv_sec, (int)h->ts.tv_usec);
- }
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
+ }
+ tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
+ if(yellow){
+ tcph->window=htons(-interp_ack_vect((u_char*)dccph)*1400);
+ if(-interp_ack_vect((u_char*)dccph)*1400 > 65535){
+ printf("Note: TCP Window Overflow @ %d.%d\n", (int)old->h->ts.tv_sec, (int)old->h->ts.tv_usec);
}
- if(sack){
- ack_vect2sack(s1, tcph, tcpopt, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
+ }
+ if(sack){
+ if(sack!=2 || interp_ack_vect((u_char*)dccph)){
+ ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
}
}
tcph->fin=0;
tcph->rst=0;
- /*set libpcap header lengths*/
- h->len=sizeof(struct ether_header) + sizeof(struct iphdr) + tcph->doff*4+ 1;
- h->caplen=sizeof(struct ether_header) + sizeof(struct iphdr) + tcph->doff*4+ 1;
-
- /*set length in ip header*/
- iph->tot_len=htons(sizeof(struct iphdr) + tcph->doff*4+ 1);
+ /*calculate length*/
+ len=tcph->doff*4 + 1;
}
if(dccph->dccph_type==DCCP_PKT_CLOSEREQ){//DCCP CLOSEREQ----Never seen in packet capture
if(dccph->dccph_type==DCCP_PKT_CLOSE){//DCCP CLOSE-->TCP FIN,ACK
dbgprintf(2,"Packet Type: Close\n");
- if(s1 && dccph->dccph_sport==s1->addr){//determine which side of connection is sending this packet
- if(green){
- tcph->ack_seq=htonl(convert_ack(s2,ntohl(dccphack->dccph_ack_nr_low)));
- }else{
- tcph->ack_seq=htonl(convert_ack(s2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
- }
- tcph->seq=htonl(add_new_seq(s1, ntohl(dccphex->dccph_seq_low),1));
- if(yellow){
- tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(s2, ntohl(dccphack->dccph_ack_nr_low)));
- }
- if(sack){
- ack_vect2sack(s2, tcph, tcpopt, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
- }
+ update_state(h1,CLOSE);
+ if(green){
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
}else{
- if(green){
- tcph->ack_seq=htonl(convert_ack(s1,ntohl(dccphack->dccph_ack_nr_low)));
- }else{
- tcph->ack_seq=htonl(convert_ack(s1,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
- }
- tcph->seq=htonl(add_new_seq(s2, ntohl(dccphex->dccph_seq_low),1));
- if(yellow){
- tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(s1, ntohl(dccphack->dccph_ack_nr_low)));
- }
- if(sack){
- ack_vect2sack(s1, tcph, tcpopt, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
+ }
+ tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
+ if(yellow){
+ tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
+ }
+ if(sack){
+ if(sack!=2 || interp_ack_vect((u_char*)dccph)){
+ ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
}
}
tcph->fin=1;
tcph->rst=0;
- /*set libpcap header lengths*/
- h->len=sizeof(struct ether_header) + sizeof(struct iphdr) + tcph->doff*4;
- h->caplen=sizeof(struct ether_header) + sizeof(struct iphdr) + tcph->doff*4;
-
- /*set length in ip header*/
- iph->tot_len=htons(sizeof(struct iphdr) + tcph->doff*4);
+ /*calculate length*/
+ len=tcph->doff*4;
}
if(dccph->dccph_type==DCCP_PKT_RESET){//DCCP RESET-->TCP FIN,ACK (only seen at end of connection as CLOSE ACK)
+ if(h2->state==CLOSE){
+ update_state(h1,CLOSE);
+ }
dbgprintf(2,"Packet Type: Reset\n");
- if(s1 && dccph->dccph_sport==s1->addr){//determine which side of connection is sending this packet
- if(green){
- tcph->ack_seq=htonl(convert_ack(s2,ntohl(dccphack->dccph_ack_nr_low)));
- }else{
- tcph->ack_seq=htonl(convert_ack(s2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
- }
- tcph->seq=htonl(add_new_seq(s1, ntohl(dccphex->dccph_seq_low),1));
- if(yellow){
- tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(s2, ntohl(dccphack->dccph_ack_nr_low)));
- }
- if(sack){
- ack_vect2sack(s2, tcph, tcpopt, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
- }
+ if(green){
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
}else{
- if(green){
- tcph->ack_seq=htonl(convert_ack(s1,ntohl(dccphack->dccph_ack_nr_low)));
- }else{
- tcph->ack_seq=htonl(convert_ack(s1,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
- }
- tcph->seq=htonl(add_new_seq(s2, ntohl(dccphex->dccph_seq_low),1));
- if(yellow){
- tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(s1, ntohl(dccphack->dccph_ack_nr_low)));
- }
- if(sack){
- ack_vect2sack(s1, tcph, tcpopt, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
+ }
+ tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),1,dccph->dccph_type));
+ if(yellow){
+ tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
+ }
+ if(sack){
+ if(sack!=2 || interp_ack_vect((u_char*)dccph)){
+ ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
}
}
tcph->fin=1;
tcph->rst=0;
- /*set libpcap header lengths*/
- h->len=sizeof(struct ether_header) + sizeof(struct iphdr) + tcph->doff*4;
- h->caplen=sizeof(struct ether_header) + sizeof(struct iphdr) + tcph->doff*4;
-
- /*set length in ip header*/
- iph->tot_len=htons(sizeof(struct iphdr) + tcph->doff*4);
+ /*calculate length*/
+ len=tcph->doff*4;
}
if(dccph->dccph_type==DCCP_PKT_SYNC){//DCCP SYNC
dbgprintf(2,"Packet Type: Sync\n");
- if(s1 && dccph->dccph_sport==s1->addr){//determine which side of connection is sending this packet
- if(green){
- tcph->ack_seq=htonl(convert_ack(s2,ntohl(dccphack->dccph_ack_nr_low)));
- }else{
- tcph->ack_seq=htonl(convert_ack(s2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
- }
- tcph->seq=htonl(add_new_seq(s1, ntohl(dccphex->dccph_seq_low),0));
- if(yellow){
- tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(s2, ntohl(dccphack->dccph_ack_nr_low)));
- }else{
- tcph->window=htons(0);
- }
- if(sack){
- ack_vect2sack(s2, tcph, tcpopt, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
- }
+ if(green){
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
}else{
- if(green){
- tcph->ack_seq=htonl(convert_ack(s1,ntohl(dccphack->dccph_ack_nr_low)));
- }else{
- tcph->ack_seq=htonl(convert_ack(s1,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
- }
- tcph->seq=htonl(add_new_seq(s2, ntohl(dccphex->dccph_seq_low),0));
- if(yellow){
- tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(s1, ntohl(dccphack->dccph_ack_nr_low)));
- }else{
- tcph->window=htons(0);
- }
- if(sack){
- ack_vect2sack(s1, tcph, tcpopt, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
+ }
+ tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),0,dccph->dccph_type));
+ if(yellow){
+ tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
+ }else{
+ tcph->window=htons(0);
+ }
+ if(sack){
+ if(sack!=2 || interp_ack_vect((u_char*)dccph)){
+ ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
}
}
tcph->fin=0;
tcph->rst=0;
- /*set libpcap header lengths*/
- h->len=sizeof(struct ether_header) + sizeof(struct iphdr) + tcph->doff*4+ 0;
- h->caplen=sizeof(struct ether_header) + sizeof(struct iphdr) + tcph->doff*4+ 0;
-
- /*set length in ip header*/
- iph->tot_len=htons(sizeof(struct iphdr) + tcph->doff*4+0);
+ /*calculate length*/
+ len=tcph->doff*4;
}
if(dccph->dccph_type==DCCP_PKT_SYNCACK){//DCCP SYNACK
dbgprintf(2,"Packet Type: SyncAck\n");
- if(s1 && dccph->dccph_sport==s1->addr){//determine which side of connection is sending this packet
- if(green){
- tcph->ack_seq=htonl(convert_ack(s2,ntohl(dccphack->dccph_ack_nr_low)));
- }else{
- tcph->ack_seq=htonl(convert_ack(s2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
- }
- tcph->seq=htonl(add_new_seq(s1, ntohl(dccphex->dccph_seq_low),0));
- if(yellow){
- tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(s2, ntohl(dccphack->dccph_ack_nr_low)));
- }else{
- tcph->window=htons(0);
- }
- if(sack){
- ack_vect2sack(s2, tcph, tcpopt, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
- }
+ if(green){
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
}else{
- if(green){
- tcph->ack_seq=htonl(convert_ack(s1,ntohl(dccphack->dccph_ack_nr_low)));
- }else{
- tcph->ack_seq=htonl(convert_ack(s1,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
- }
- tcph->seq=htonl(add_new_seq(s2, ntohl(dccphex->dccph_seq_low),0));
- if(yellow){
- tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(s1, ntohl(dccphack->dccph_ack_nr_low)));
- }else{
- tcph->window=htons(0);
- }
- if(sack){
- ack_vect2sack(s1, tcph, tcpopt, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low) );
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
+ }
+ tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),0,dccph->dccph_type));
+ if(yellow){
+ tcph->window=htons(-interp_ack_vect((u_char*)dccph)*acked_packet_size(h2, ntohl(dccphack->dccph_ack_nr_low)));
+ }else{
+ tcph->window=htons(0);
+ }
+ if(sack){
+ if(sack!=2 || interp_ack_vect((u_char*)dccph)){
+ ack_vect2sack(h2, tcph, (u_char*)tcph + tcph->doff*4, (u_char*)dccph, ntohl(dccphack->dccph_ack_nr_low));
}
}
tcph->fin=0;
tcph->rst=0;
- /*set libpcap header lengths*/
- h->len=sizeof(struct ether_header) + sizeof(struct iphdr) + tcph->doff*4+0;
- h->caplen=sizeof(struct ether_header) + sizeof(struct iphdr) + tcph->doff*4+0;
-
- /*set length in ip header*/
- iph->tot_len=htons(sizeof(struct iphdr) + tcph->doff*4+0);
+ /*calculate length*/
+ len=tcph->doff*4;
}
if(dccph->dccph_type==DCCP_PKT_INVALID){//DCCP INVALID----Never seen in packet capture
dbgprintf(0,"Invalid DCCP Packet!!\n");
- exit(1);
+ return 0;
}
-return;
+
+ new->length=len;
+return 1;
}
-/*Parse Ack Vector Options*/
+/*Parse Ack Vector Options
+ * Returns the Number of packets since last recorded loss*/
unsigned int interp_ack_vect(u_char* hdr)
{
int hdrlen=((struct dccp_hdr*)hdr)->dccph_doff*4;
/*parse options*/
while(optlen > 0){
- len=*(opt+1);
/*One byte options (no length)*/
if(*opt< 32){
continue;
}
+ /*Check option length*/
+ len=*(opt+1);
+ if(len > optlen){
+ dbgprintf(0, "Warning: Option would extend into packet data\n");
+ return additional;
+ }
+
/*Ack Vector Option*/
if(*opt==38 || *opt==39){
tmp=len-2;
if((*cur & 0xC0)==0x00){ //received packet
bp+= (*cur & 0x3F)+1;
}
+
+ if(((*cur& 0xC0)!= 0xC0) && ((*cur& 0xC0)!= 0x00) && ((*cur& 0xC0)!= 0x40)){
+ dbgprintf(1, "Warning: Invalid Ack Vector!! (Linux will handle poorly!)\n");
+ }
tmp--;
cur++;
}
/* Setup Sequence Number Structure*/
-u_int32_t initialize_seq(struct seq_num **seq, __be16 source, __be32 initial)
+u_int32_t initialize_seq(struct host *seq, __be32 initial)
{
- /*allocate structure*/
- *seq=(struct seq_num*)malloc(sizeof(struct seq_num));
- if(*seq==NULL){
- dbgprintf(0,"Can't Allocate Memory!\n");
- exit(1);
- }
-
/*set default values*/
- (*seq)->cur=0;
- (*seq)->addr=source;
- (*seq)->size=TBL_SZ;
+ seq->cur=0;
+ seq->size=TBL_SZ;
/*allocate table*/
- (*seq)->table=(struct tbl*)malloc(sizeof(struct tbl)*TBL_SZ);
- if((*seq)->table==NULL){
+ seq->table=(struct tbl*)malloc(sizeof(struct tbl)*TBL_SZ);
+ if(seq->table==NULL){
dbgprintf(0,"Can't Allocate Memory!\n");
exit(1);
}
/*add first sequence number*/
- (*seq)->table[0].old=initial;
- (*seq)->table[0].new=initial;
- (*seq)->table[0].size=1; /* size is actually zero; this is a convient way to get
- these packets counted in the sequence number space*/
+ seq->table[0].old=initial;
+ seq->table[0].new=initial;
+ seq->table[0].type=DCCP_PKT_REQUEST;
+ seq->table[0].size=0;
+ update_state(seq,OPEN);
return initial;
}
/*Convert Sequence Numbers*/
-u_int32_t add_new_seq(struct seq_num *seq, __be32 num, int size)
+u_int32_t add_new_seq(struct host *seq, __be32 num, int size, enum dccp_pkt_type type)
{
int prev;
if(seq==NULL){
exit(1);
}
+ if(seq->table==NULL){
+ dbgprintf(1, "Warning: Connection uninitialized\n");
+ return initialize_seq(seq, num);
+ }
+
/*account for missing packets*/
+ if(num - seq->table[seq->cur].old +1 >=100){
+ dbgprintf(1,"Missing more than 100 packets!\n");
+ }
while(seq->table[seq->cur].old +1 < num && seq->table[seq->cur].old +1 > 0){
prev=seq->cur;
- dbgprintf(1,"Missing Packet: %X\n",seq->table[prev].new+1);
+ if(num - seq->table[seq->cur].old +1 <100){
+ dbgprintf(1,"Missing Packet: %X\n",seq->table[prev].new+1);
+ }
seq->cur=(seq->cur+1)%(seq->size);/*find next available table slot*/
seq->table[seq->cur].old=seq->table[prev].old+1;
seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
seq->table[seq->cur].size=size;
+ seq->table[seq->cur].type=type;
}
prev=seq->cur;
seq->cur=(seq->cur+1)%(seq->size);/*find next available table slot*/
seq->table[seq->cur].old=num;
- seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
seq->table[seq->cur].size=size;
-return seq->table[seq->cur].new;
+ seq->table[seq->cur].type=type;
+ if(seq->table[prev].type==DCCP_PKT_REQUEST || seq->table[prev].type==DCCP_PKT_RESPONSE){
+ seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
+ seq->table[seq->cur].size=1;
+ return seq->table[prev].new + seq->table[prev].size+1;
+ }
+ if(type==DCCP_PKT_DATA || type==DCCP_PKT_DATAACK || type==DCCP_PKT_ACK){
+ seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
+ return seq->table[seq->cur].new+1;
+ }
+ if(type==DCCP_PKT_SYNC || type==DCCP_PKT_SYNCACK){
+ seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
+ return seq->table[seq->cur].new;
+ }
+ seq->table[seq->cur].new=seq->table[prev].new + seq->table[prev].size;
+return seq->table[seq->cur].new +1;
}
/*Convert Ack Numbers*/
-u_int32_t convert_ack(struct seq_num *seq, __be32 num)
+u_int32_t convert_ack(struct host *seq, __be32 num)
{
if(seq==NULL){
dbgprintf(0,"ERROR NULL POINTER!\n");
exit(1);
}
+ if(seq->table==NULL){
+ dbgprintf(1, "Warning: Connection uninitialized\n");
+ initialize_seq(seq, num);
+ }
+
/*loop through table looking for the DCCP ack number*/
for(int i=0; i < seq->size; i++){
if(seq->table[i].old==num){
- return seq->table[i].new +1; /*TCP acks the sequence number plus 1*/
+ return seq->table[i].new + seq->table[i].size + 1; /*TCP acks the sequence number plus 1*/
}
}
/* Get size of packet being acked*/
-int acked_packet_size(struct seq_num *seq, __be32 num)
+int acked_packet_size(struct host *seq, __be32 num)
{
if(seq==NULL){
dbgprintf(0,"ERROR NULL POINTER!\n");
exit(1);
}
+ if(seq->table==NULL){
+ dbgprintf(1, "Warning: Connection uninitialized\n");
+ initialize_seq(seq, num);
+ }
+
/*loop through table looking for the DCCP ack number*/
for(int i=0; i < seq->size; i++){
if(seq->table[i].old==num){
/*Ack Vector to SACK Option*/
-void ack_vect2sack(struct seq_num *seq, struct tcphdr *tcph, u_char* tcpopts, u_char* dccphdr, __be32 dccpack)
+void ack_vect2sack(struct host *seq, struct tcphdr *tcph, u_char* tcpopts, u_char* dccphdr, __be32 dccpack)
{
int hdrlen=((struct dccp_hdr*)dccphdr)->dccph_doff*4;
int optlen;
opt=dccphdr + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
/*setup tcp pointers*/
- num_blocks=2;
+ num_blocks=4;
*tcpopts=5;
tlen=tcpopts+1;
temp=tlen;
/*parse options*/
while(optlen > 0){
- len=*(opt+1);
/*One byte options (no length)*/
if(*opt< 32){
continue;
}
+ len=*(opt+1);
+ if(len > optlen){
+ dbgprintf(0, "Warning: Option would extend into packet data\n");
+ break;
+ }
+
/*Ack Vector Option*/
if(*opt==38 || *opt==39){
tmp=len-2;