/******************************************************************************
-Author: Samuel Jero
+Utility to convert a DCCP flow to a TCP flow for DCCP analysis via
+ tcptrace.
-Date: 7/2011
+Copyright (C) 2013 Samuel Jero <sj323707@ohio.edu>
-Description: Program to convert a DCCP flow to a TCP flow for DCCP analysis via
- tcptrace.
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Author: Samuel Jero <sj323707@ohio.edu>
+Date: 02/2013
Notes:
- 1)CCID2 ONLY
- 2)DCCP MUST use 48 bit sequence numbers
- 3)Checksums are not computed (they are zeroed)
- 4)Only implements those packet types normally used in a session
- 5)DCCP Ack packets show up as TCP packets containing one byte
- 6)Very little error checking of packet headers
+ 1)DCCP MUST use 48 bit sequence numbers
+ 2)DCCP Ack packets show up as TCP packets containing one byte
******************************************************************************/
#include "dccp2tcp.h"
+#define DCCP2TCP_VERSION 1.6
+#define COPYRIGHT_YEAR 2013
+
+
int debug=0; /*set to 1 to turn on debugging information*/
int yellow=0; /*tcptrace yellow line as currently acked packet*/
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 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);
-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 host *seq, __be16 source, __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);
+int handle_request(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2);
+int handle_response(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2);
+int handle_dataack(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2);
+int handle_ack(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2);
+int handle_closereq(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2);
+int handle_close(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2);
+int handle_reset(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2);
+int handle_sync(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2);
+int handle_syncack(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2);
+int handle_data(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2);
+int parse_options(const u_char* opt_start, int len,
+ const struct const_packet* pkt, struct hcon* A, struct hcon* B);
+int process_feature(const u_char* feat, int len, int confirm, int L,
+ const struct const_packet* pkt, struct hcon* A, struct hcon* B);
+void ack_vect2sack(struct hcon *seq, struct tcphdr *tcph,
+ u_char* tcpopts, u_char* dccphdr, d_seq_num dccpack, struct hcon* o_hcn);
+void version();
+void usage();
/*Parse commandline options and open files*/
char *tfile=NULL;
/*parse commandline options*/
- if(argc<3 || argc > 9){
- dbgprintf(0, "Usage: dccp2tcp dccp_file tcp_file [-d] [-y] [-g] [-s]\n");
- exit(1);
+ if(argc > 9){
+ usage();
}
/*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){
tfile=argv[i]; /*assign second non-dash argument to the dccp file*/
}else{
- dbgprintf(0,"Usage: dccp2tcp dccp_file tcp_file [-d] [-y] [-g] [-s]\n");
- exit(1);
+ usage();
}
}
}else{
- if(argv[i][1]=='d' && strlen(argv[i])==2){ /*debug option*/
+ if(argv[i][1]=='v' && strlen(argv[i])==2){ /* -v */
debug++;
- }
- if(argv[i][1]=='y' && strlen(argv[i])==2){ /*yellow option*/
+ }else if(argv[i][1]=='y' && strlen(argv[i])==2){ /* -y */
yellow=1;
- }
- if(argv[i][1]=='g' && strlen(argv[i])==2){ /*green option*/
+ }else if(argv[i][1]=='g' && strlen(argv[i])==2){ /* -g */
green=1;
- }
- if(argv[i][1]=='s' && strlen(argv[i])==2){ /*sack option*/
+ }else if(argv[i][1]=='s' && strlen(argv[i])==2){ /* -s */
sack++;
+ }else if(argv[i][1]=='h' && strlen(argv[i])==2){ /* -h */
+ usage();
+ }else if(argv[i][1]=='V' && strlen(argv[i])==2){ /* -V */
+ version();
+ }else{
+ usage();
}
}
}
if(dfile==NULL || tfile==NULL){
- dbgprintf(0,"Usage: dccp2tcp dccp_file tcp_file [-d] [-y] [-g] [-s]\n");
- exit(1);
+ usage();
}
/*all options validated*/
if(debug){
- dbgprintf(1,"Debug On\n");
if(green){
dbgprintf(1,"Tcptrace green line at highest acknowledgment\n");
}else{
/*close files*/
pcap_close(in);
pcap_dump_close(out);
+
+ /*Delete all connections*/
+ cleanup_connections();
return 0;
}
old.h=h;
old.length=h->caplen;
old.data=bytes;
+ old.dest_id=NULL;
+ old.src_id=NULL;
new.h=&nh;
new.length=MAX_PACKET;
+ new.dest_id=NULL;
+ new.src_id=NULL;
/*create buffer for new packet*/
new.data=ndata=malloc(MAX_PACKET);
return;
}
-
/*do all the dccp to tcp conversions*/
int convert_packet(struct packet *new, const struct const_packet* old)
-{
+{
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;
+ struct hcon *h1=NULL;
+ struct hcon *h2=NULL;
+ char buf1[100];
+ char buf2[100];
/*Safety checks*/
if(!new || !old || !new->data || !old->data || !new->h || !old->h){
exit(1);
return 0;
}
- if(old->length < sizeof(struct dccp_hdr) || new->length < sizeof(struct dccp_hdr)){
- dbgprintf(0, "Error: Convert Packet Function given packet of wrong size!\n");
+ 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;
}
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)));
+ dbgprintf(2,"Sequence Number: %llu\n", (unsigned long long)
+ (((unsigned long)ntohs(dccph->dccph_seq)<<32) + ntohl(dccphex->dccph_seq_low)));
+
+ /*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;
+ }
/*Get Hosts*/
- if(get_host(new->src_id, new->dest_id, dccph->dccph_sport, dccph->dccph_dport, &h1, &h2)){
+ if(get_host(new->src_id, new->dest_id, new->id_len, dccph->dccph_sport,
+ dccph->dccph_dport, dccph->dccph_type,&h1, &h2)){
dbgprintf(0,"Error: Can't Get Hosts!\n");
return 0;
}
dbgprintf(0, "Error: Can't Get Hosts!\n");
return 0;
}
-
- /*determine data length*/
- datalength=old->length - dccph->dccph_doff*4;
- pd=old->data + dccph->dccph_doff*4;
+ if(h1->state==IGNORE || h2->state==IGNORE){
+ if(old->print_id){
+ dbgprintf(2,"Ignoring packet between %s:%i and %s:%i\n",
+ old->print_id(buf1,100,old->src_id,old->id_len),ntohs(dccph->dccph_sport),
+ old->print_id(buf2,100,old->dest_id,old->id_len), ntohs(dccph->dccph_dport));
+ }else{
+ dbgprintf(2,"Ignoring packet between %i and %i\n",
+ ntohs(dccph->dccph_sport), ntohs(dccph->dccph_dport));
+ }
+ return 0;
+ }
/*set TCP standard features*/
tcph->source=dccph->dccph_sport;
tcph->window=htons(30000);
}
- /*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);
+ /*Process DCCP Packet Types*/
+ switch(dccph->dccph_type){
+ case DCCP_PKT_REQUEST:
+ dbgprintf(2,"Packet Type: Request\n");
+ if(!handle_request(new, old, h1, h2)){
+ return 0;
+ }
+ break;
+ case DCCP_PKT_RESPONSE:
+ dbgprintf(2,"Packet Type: Response\n");
+ if(!handle_response(new,old,h1,h2)){
+ return 0;
+ }
+ break;
+ case DCCP_PKT_DATA:
+ if(!handle_data(new,old,h1,h2)){
+ return 0;
+ }
+ break;
+ case DCCP_PKT_DATAACK:
+ dbgprintf(2,"Packet Type: DataAck\n");
+ if(!handle_dataack(new,old,h1,h2)){
+ return 0;
+ }
+ break;
+ case DCCP_PKT_ACK:
+ dbgprintf(2,"Packet Type: Ack\n");
+ if(!handle_ack(new,old,h1,h2)){
+ return 0;
}
- tcph->ack_seq=htonl(0);
- tcph->seq=htonl(initialize_seq(h1, 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++;
+ break;
+ case DCCP_PKT_CLOSEREQ:
+ dbgprintf(2,"Packet Type: CloseReq\n");
+ if(!handle_closereq(new,old,h1,h2)){
+ return 0;
}
+ break;
+ case DCCP_PKT_CLOSE:
+ dbgprintf(2,"Packet Type: Close\n");
+ if(!handle_close(new,old,h1,h2)){
+ return 0;
+ }
+ break;
+ case DCCP_PKT_RESET:
+ dbgprintf(2,"Packet Type: Reset\n");
+ if(!handle_reset(new,old,h1,h2)){
+ return 0;
+ }
+ break;
+ case DCCP_PKT_SYNC:
+ dbgprintf(2,"Packet Type: Sync\n");
+ if(!handle_sync(new,old,h1,h2)){
+ return 0;
+ }
+ break;
+ case DCCP_PKT_SYNCACK:
+ dbgprintf(2,"Packet Type: SyncAck\n");
+ if(!handle_syncack(new,old,h1,h2)){
+ return 0;
+ }
+ break;
+ default:
+ dbgprintf(0,"Invalid DCCP Packet!!\n");
+ return 0;
+ break;
+ }
- /*calculate length*/
- len=tcph->doff*4;
- }
+ /*Compute TCP checksums*/
+ if(new->id_len==IP4_ADDR_LEN){
+ tcph->check=0;
+ tcph->check=ipv4_pseudohdr_chksum(new->data,
+ new->length, new->dest_id, new->src_id, 6);
+ }else if(new->id_len==IP6_ADDR_LEN){
+ tcph->check=0;
+ tcph->check=ipv6_pseudohdr_chksum(new->data,
+ new->length, new->dest_id, new->src_id, 6);
+ }else{
+ tcph->check=0;
+ dbgprintf(2,"Unknown ID Length, can't do checksums\n");
}
- if(dccph->dccph_type==DCCP_PKT_RESPONSE){//DCCP RESPONSE-->TCP SYN,ACK
- dbgprintf(2,"Packet Type: Response\n");
- 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, 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=(u_char*)(new->data + tcph->doff*4);
- *tcpopt=4;
- *(tcpopt+1)=2;
- tcph->doff++;
- }
+ return 1;
+}
- /*calculate length*/
- len=tcph->doff*4;
- }
+int handle_request(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
+{
+ struct tcphdr *tcph;
+ struct dccp_hdr *dccph;
+ struct dccp_hdr_ext *dccphex;
+ int datalength;
+ int optlen;
+ u_char* tcpopt;
+ const u_char* dccpopt;
+
+ /*length check*/
+ if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext)+sizeof(struct dccp_hdr_request)){
+ return 0;
}
- if(dccph->dccph_type==DCCP_PKT_DATA){//DCCP DATA----Never seen in packet capture
- dbgprintf(0,"DCCP Data packet not yet implemented\n");
- exit(1);
+ /*cast header pointers*/
+ tcph=(struct tcphdr*)new->data;
+ dccph=(struct dccp_hdr*)old->data;
+ dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
+
+ /*determine data length*/
+ datalength=old->length - dccph->dccph_doff*4;
+
+ /*Process DCCP Options*/
+ dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext)+sizeof(struct dccp_hdr_request);
+ optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr)-sizeof(struct dccp_hdr_ext)-sizeof(struct dccp_hdr_request);
+ if(!parse_options(dccpopt,optlen,old,h1,h2)){
+ return 0;
}
- if(dccph->dccph_type==DCCP_PKT_DATAACK){//DCCP DATAACK-->TCP ACK with data
- dbgprintf(2,"Packet Type: DataAck\n");
- if(green){
- tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
- }else{
- tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph)));
- }
+ /*Do conversion*/
+ if(yellow){
+ tcph->window=htons(0);
+ }
+ tcph->ack_seq=htonl(0);
+ if(h1->state==INIT){
+ tcph->seq=htonl(initialize_hcon(h1, ntohl(dccphex->dccph_seq_low)));
+ }else{
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->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++;
+ }
- tcph->syn=0;
- tcph->ack=1;
- tcph->fin=0;
- tcph->rst=0;
+ /*calculate length*/
+ new->length=tcph->doff*4;
+ return 1;
+}
- /*copy data*/
- npd=new->data + tcph->doff*4;
- memcpy(npd, pd, datalength);
+int handle_response(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
+{
+ struct tcphdr *tcph;
+ struct dccp_hdr *dccph;
+ struct dccp_hdr_ext *dccphex;
+ struct dccp_hdr_ack_bits *dccphack;
+ int optlen;
+ u_char* tcpopt;
+ const u_char* dccpopt;
- /*calculate length*/
- len= tcph->doff*4 + datalength;
+ /*length check*/
+ if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext)
+ + sizeof(struct dccp_hdr_ack_bits)+sizeof(struct dccp_hdr_request)){
+ return 0;
}
- if(dccph->dccph_type==DCCP_PKT_ACK){ //DCCP ACK -->TCP ACK with no data
- dbgprintf(2,"Packet Type: Ack\n");
- if(green){
- tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
- }else{
- 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){
- 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->syn=0;
- tcph->ack=1;
- tcph->fin=0;
- tcph->rst=0;
+ /*cast header pointers*/
+ 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));
- /*calculate length*/
- len=tcph->doff*4 + 1;
+ /*Process DCCP Options*/
+ dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) +
+ sizeof(struct dccp_hdr_ack_bits) + sizeof(struct dccp_hdr_request);
+ optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext)
+ - sizeof(struct dccp_hdr_ack_bits) - sizeof(struct dccp_hdr_request);
+ if(!parse_options(dccpopt,optlen,old,h1,h2)){
+ return 0;
}
- if(dccph->dccph_type==DCCP_PKT_CLOSEREQ){//DCCP CLOSEREQ----Never seen in packet capture
- dbgprintf(0,"DCCP CloseReq not yet implemented\n");
- exit(1);
+ /*Do conversion*/
+ if(h2->state!=OPEN){
+ dbgprintf(0,"Warning: DCCP Response without a Request!!\n");
+ }
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
+ h1->high_ack=ntohl(tcph->ack_seq);
+ if(yellow){
+ tcph->window=htons(0);
+ }
+ if(h1->state==INIT){
+ tcph->seq=htonl(initialize_hcon(h1, 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=(u_char*)(new->data + tcph->doff*4);
+ *tcpopt=4;
+ *(tcpopt+1)=2;
+ tcph->doff++;
}
- if(dccph->dccph_type==DCCP_PKT_CLOSE){//DCCP CLOSE-->TCP FIN,ACK
- dbgprintf(2,"Packet Type: Close\n");
- update_state(h1,CLOSE);
- if(green){
- tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
- }else{
- 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) );
- }
- }
+ /*calculate length*/
+ new->length=tcph->doff*4;
+ return 1;
+}
- tcph->syn=0;
- tcph->ack=1;
- tcph->fin=1;
- tcph->rst=0;
+int handle_dataack(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
+{
+ struct tcphdr *tcph;
+ struct dccp_hdr *dccph;
+ struct dccp_hdr_ext *dccphex;
+ struct dccp_hdr_ack_bits *dccphack;
+ int datalength;
+ int optlen;
+ const u_char* pd;
+ u_char* npd;
+ const u_char* dccpopt;
- /*calculate length*/
- len=tcph->doff*4;
+ /*length check*/
+ if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
+ return 0;
}
- 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(green){
- tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
- }else{
- 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) );
- }
- }
+ /*cast header pointers*/
+ 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));
- tcph->syn=0;
- tcph->ack=1;
- tcph->fin=1;
- tcph->rst=0;
+ /*determine data length*/
+ datalength=old->length - dccph->dccph_doff*4;
+ pd=old->data + dccph->dccph_doff*4;
- /*calculate length*/
- len=tcph->doff*4;
+ /*Process DCCP Options*/
+ dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
+ optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
+ if(!parse_options(dccpopt,optlen,old,h1,h2)){
+ return 0;
}
- if(dccph->dccph_type==DCCP_PKT_SYNC){//DCCP SYNC
- dbgprintf(2,"Packet Type: Sync\n");
- if(green){
- tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
- }else{
- 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) );
- }
+ /*Do Conversion*/
+ if(green){
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
+ }else{
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
+ }
+ h1->high_ack=ntohl(tcph->ack_seq);
+ 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),h1);
}
+ }
+ tcph->syn=0;
+ tcph->ack=1;
+ tcph->fin=0;
+ tcph->rst=0;
+
+ /*copy data*/
+ npd=new->data + tcph->doff*4;
+ memcpy(npd, pd, datalength);
+
+ /*calculate length*/
+ new->length=tcph->doff*4 + datalength;
+ return 1;
+}
- tcph->syn=0;
- tcph->ack=1;
- tcph->fin=0;
- tcph->rst=0;
+int handle_ack(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
+{
+ struct tcphdr *tcph;
+ struct dccp_hdr *dccph;
+ struct dccp_hdr_ext *dccphex;
+ struct dccp_hdr_ack_bits *dccphack;
+ int optlen;
+ const u_char* dccpopt;
- /*calculate length*/
- len=tcph->doff*4;
+ /*length check*/
+ if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
+ return 0;
}
- if(dccph->dccph_type==DCCP_PKT_SYNCACK){//DCCP SYNACK
- dbgprintf(2,"Packet Type: SyncAck\n");
- if(green){
- tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)));
- }else{
- 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);
+ /*cast header pointers*/
+ 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));
+
+ /*Process DCCP Options*/
+ dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
+ optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
+ if(!parse_options(dccpopt,optlen,old,h1,h2)){
+ return 0;
+ }
+
+ /*Do Conversion*/
+ if(green){
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
+ }else{
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
+ }
+ h1->high_ack=ntohl(tcph->ack_seq);
+ 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){
+ dbgprintf(0,"Note: TCP Window Overflow @ %d.%d\n", (int)old->h->ts.tv_sec, (int)old->h->ts.tv_usec);
}
- 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));
- }
+ }
+ 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),h1);
}
+ }
- tcph->syn=0;
- tcph->ack=1;
- tcph->fin=0;
- tcph->rst=0;
+ tcph->syn=0;
+ tcph->ack=1;
+ tcph->fin=0;
+ tcph->rst=0;
- /*calculate length*/
- len=tcph->doff*4;
+ /*calculate length*/
+ new->length=tcph->doff*4 + 1;
+ return 1;
+}
+
+int handle_closereq(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
+{
+ struct tcphdr *tcph;
+ struct dccp_hdr *dccph;
+ struct dccp_hdr_ext *dccphex;
+ struct dccp_hdr_ack_bits *dccphack;
+ int optlen;
+ const u_char* dccpopt;
+
+ /*length check*/
+ if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
+ return 0;
}
- if(dccph->dccph_type==DCCP_PKT_INVALID){//DCCP INVALID----Never seen in packet capture
- dbgprintf(0,"Invalid DCCP Packet!!\n");
+ /*cast header pointers*/
+ 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));
+
+ /*Process DCCP Options*/
+ dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
+ optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
+ if(!parse_options(dccpopt,optlen,old,h1,h2)){
return 0;
}
- new->length=len;
-return 1;
-}
+ /*Do Conversion*/
+ if(green){
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
+ }else{
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
+ }
+ h1->high_ack=ntohl(tcph->ack_seq);
+ 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),h1);
+ }
+ }
+
+ tcph->syn=0;
+ tcph->ack=1;
+ tcph->fin=1;
+ tcph->rst=0;
+ /*calculate length*/
+ new->length=tcph->doff*4;
+ return 1;
+}
-/*Parse Ack Vector Options
- * Returns the Number of packets since last recorded loss*/
-unsigned int interp_ack_vect(u_char* hdr)
+int handle_close(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
{
- int hdrlen=((struct dccp_hdr*)hdr)->dccph_doff*4;
- //struct dccp_hdr_ext* e=(struct dccp_hdr_ext*)hdr + sizeof(struct dccp_hdr);
- int optlen;
- int len;
- int tmp;
- int bp=0;
- int additional=0;
- u_char* opt;
- u_char* cur;
+ struct tcphdr *tcph;
+ struct dccp_hdr *dccph;
+ struct dccp_hdr_ext *dccphex;
+ struct dccp_hdr_ack_bits *dccphack;
+ int optlen;
+ const u_char* dccpopt;
- /*setup pointer to DCCP options and determine how long the options are*/
- optlen=hdrlen-sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
- opt=hdr + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
+ /*length check*/
+ if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
+ return 0;
+ }
- /*parse options*/
- while(optlen > 0){
- len=*(opt+1);
+ /*cast header pointers*/
+ 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));
- /*One byte options (no length)*/
- if(*opt< 32){
- optlen--;
- opt++;
- continue;
+ /*Process DCCP Options*/
+ dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
+ optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
+ if(!parse_options(dccpopt,optlen,old,h1,h2)){
+ return 0;
+ }
+
+ /*Do Conversion*/
+ update_state(h1,CLOSE);
+ if(green){
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
+ }else{
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
+ }
+ h1->high_ack=ntohl(tcph->ack_seq);
+ 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),h1);
}
+ }
- /*Ack Vector Option*/
- if(*opt==38 || *opt==39){
- tmp=len-2;
- cur=opt+2;
- /*loop through Vector*/
- while(tmp > 0){
- /*ack vector works BACKWARDS through time*/
+ tcph->syn=0;
+ tcph->ack=1;
+ tcph->fin=1;
+ tcph->rst=0;
- /*keep track of total packets recieved and if
- a packet is lost, subtract all packets received
- after that*/
- if((*cur & 0xC0)==0xC0 || (*cur & 0xC0)==0x40){ //lost packet
- bp+=(*cur & 0x3F)+1;
- additional= -bp;
- }
-
- if((*cur & 0xC0)==0x00){ //received packet
- bp+= (*cur & 0x3F)+1;
- }
+ /*calculate length*/
+ new->length=tcph->doff*4;
+ return 1;
+}
- if(((*cur& 0xC0)!= 0xC0) && ((*cur& 0xC0)!= 0x00) && ((*cur& 0xC0)!= 0x40)){
- dbgprintf(1, "Warning: Invalid Ack Vector!! (Linux will handle poorly!) -- %X\n", *cur);
- }
- tmp--;
- cur++;
- }
+int handle_reset(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
+{
+ struct tcphdr *tcph;
+ struct dccp_hdr *dccph;
+ struct dccp_hdr_ext *dccphex;
+ struct dccp_hdr_ack_bits *dccphack;
+ int optlen;
+ const u_char* dccpopt;
+
+ /*length check*/
+ if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
+ return 0;
+ }
+
+ /*cast header pointers*/
+ 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));
+
+ /*Process DCCP Options*/
+ dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
+ optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
+ if(!parse_options(dccpopt,optlen,old,h1,h2)){
+ return 0;
+ }
+
+ /*Do Conversion*/
+ if(h2->state==CLOSE){
+ update_state(h1,CLOSE);
+ }
+ if(green){
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
+ }else{
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
+ }
+ h1->high_ack=ntohl(tcph->ack_seq);
+ 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),h1);
}
-
- optlen-=len;
- opt+=len;
}
- dbgprintf(2,"Ack vector adding: %i\n", additional);
-return additional;
-}
+ tcph->syn=0;
+ tcph->ack=1;
+ tcph->fin=1;
+ tcph->rst=0;
+ /*calculate length*/
+ new->length=tcph->doff*4;
+ return 1;
+}
-/* Setup Sequence Number Structure*/
-u_int32_t initialize_seq(struct host *seq, __be16 source, __be32 initial)
+int handle_sync(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
{
- /*set default values*/
- seq->cur=0;
- seq->size=TBL_SZ;
-
- /*allocate table*/
- seq->table=(struct tbl*)malloc(sizeof(struct tbl)*TBL_SZ);
- if(seq->table==NULL){
- dbgprintf(0,"Can't Allocate Memory!\n");
- exit(1);
+ struct tcphdr *tcph;
+ struct dccp_hdr *dccph;
+ struct dccp_hdr_ext *dccphex;
+ struct dccp_hdr_ack_bits *dccphack;
+ int optlen;
+ const u_char* dccpopt;
+
+ /*length check*/
+ if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
+ return 0;
}
- /*add first sequence number*/
- 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;
-}
+ /*cast header pointers*/
+ 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));
+ /*Process DCCP Options*/
+ dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
+ optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
+ if(!parse_options(dccpopt,optlen,old,h1,h2)){
+ return 0;
+ }
-/*Convert Sequence Numbers*/
-u_int32_t add_new_seq(struct host *seq, __be32 num, int size, enum dccp_pkt_type type)
-{
- int prev;
- if(seq==NULL){
- dbgprintf(0,"ERROR NULL POINTER!\n");
- exit(1);
+ /*Do Conversion*/
+ if(green){
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
+ }else{
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
+ }
+ h1->high_ack=ntohl(tcph->ack_seq);
+ 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),h1);
+ }
}
-
- if(seq->table==NULL){
- dbgprintf(1, "Warning: Connection uninitialized\n");
- return initialize_seq(seq, 0, num);
- }
-
- /*account for missing packets*/
- 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);
- 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].size=size;
- 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;
-}
+ tcph->syn=0;
+ tcph->ack=1;
+ tcph->fin=0;
+ tcph->rst=0;
-/*Convert Ack Numbers*/
-u_int32_t convert_ack(struct host *seq, __be32 num)
+ /*calculate length*/
+ new->length=tcph->doff*4;
+ return 1;
+}
+
+int handle_syncack(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
{
- if(seq==NULL){
- dbgprintf(0,"ERROR NULL POINTER!\n");
- exit(1);
+ struct tcphdr *tcph;
+ struct dccp_hdr *dccph;
+ struct dccp_hdr_ext *dccphex;
+ struct dccp_hdr_ack_bits *dccphack;
+ int optlen;
+ const u_char* dccpopt;
+
+ /*length check*/
+ if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits)){
+ return 0;
}
- if(seq->table==NULL){
- dbgprintf(1, "Warning: Connection uninitialized\n");
- initialize_seq(seq, 0, num);
+ /*cast header pointers*/
+ 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));
+
+ /*Process DCCP Options*/
+ dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
+ optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
+ if(!parse_options(dccpopt,optlen,old,h1,h2)){
+ return 0;
}
- /*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 + seq->table[i].size + 1; /*TCP acks the sequence number plus 1*/
+ /*Do Conversion*/
+ if(green){
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low),h1));
+ }else{
+ tcph->ack_seq=htonl(convert_ack(h2,ntohl(dccphack->dccph_ack_nr_low)+interp_ack_vect((u_char*)dccph),h1));
+ }
+ h1->high_ack=ntohl(tcph->ack_seq);
+ 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),h1);
}
}
-
- dbgprintf(1, "Error: Address Not Found! looking for: %X\n", num);
-return 0;
-}
+ tcph->syn=0;
+ tcph->ack=1;
+ tcph->fin=0;
+ tcph->rst=0;
+
+ /*calculate length*/
+ new->length=tcph->doff*4;
+ return 1;
+}
-/* Get size of packet being acked*/
-int acked_packet_size(struct host *seq, __be32 num)
+int handle_data(struct packet* new, const struct const_packet* old, struct hcon* h1, struct hcon* h2)
{
- if(seq==NULL){
- dbgprintf(0,"ERROR NULL POINTER!\n");
- exit(1);
+ struct tcphdr *tcph;
+ struct dccp_hdr *dccph;
+ struct dccp_hdr_ext *dccphex;
+ int datalength;
+ int optlen;
+ const u_char* pd;
+ u_char* npd;
+ const u_char* dccpopt;
+
+ /*length check*/
+ if(new->length < sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext)){
+ return 0;
}
- if(seq->table==NULL){
- dbgprintf(1, "Warning: Connection uninitialized\n");
- initialize_seq(seq, 0, num);
+ /*cast header pointers*/
+ tcph=(struct tcphdr*)new->data;
+ dccph=(struct dccp_hdr*)old->data;
+ dccphex=(struct dccp_hdr_ext*)(old->data+sizeof(struct dccp_hdr));
+
+ /*determine data length*/
+ datalength=old->length - dccph->dccph_doff*4;
+ pd=old->data + dccph->dccph_doff*4;
+
+ /*Process DCCP Options*/
+ dccpopt=old->data + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext);
+ optlen=dccph->dccph_doff*4 - sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext);
+ if(!parse_options(dccpopt,optlen,old,h1,h2)){
+ return 0;
}
- /*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].size;
+ /*Do conversion*/
+ tcph->ack_seq=htonl(h1->high_ack);
+ tcph->seq=htonl(add_new_seq(h1, ntohl(dccphex->dccph_seq_low),datalength, dccph->dccph_type));
+ tcph->syn=0;
+ tcph->ack=1;
+ tcph->fin=0;
+ tcph->rst=0;
+
+ /*copy data*/
+ npd=new->data + tcph->doff*4;
+ memcpy(npd, pd, datalength);
+
+ /*calculate length*/
+ new->length=tcph->doff*4 + datalength;
+ return 1;
+}
+
+int parse_options(const u_char* opt_start, int len, const struct const_packet* pkt,
+ struct hcon* A, struct hcon* B)
+{
+ int optlen;
+ int length;
+ const u_char* opt;
+ char buf1[100];
+ char buf2[100];
+
+ /*setup pointer to DCCP options and determine how long the options are*/
+ optlen=len;
+ opt=opt_start;
+
+ /*parse options*/
+ while(optlen > 0){
+ /*One byte options (no length)*/
+ if(*opt< 32){
+ optlen--;
+ opt++;
+ continue;
+ }
+
+ /*Check option length*/
+ length=*(opt+1);
+ if(length > optlen){
+ dbgprintf(0, "Warning: Option would extend into packet data\n");
+ return 0;
+ }
+ if(length < 2){
+ dbgprintf(0, "Warning: Bad Option!\n");
+ return 0;
+ }
+
+ /*Ack Vector Option*/
+ if(*opt==38 || *opt==39){
+ if(B->type==UNKNOWN){
+ B->type=CCID2;
+ if(pkt->print_id){
+ dbgprintf(1,"Half-connection from %s:%i to %s:%i probably using CCID 2\n",
+ pkt->print_id(buf1,100,pkt->dest_id,pkt->id_len),ntohs(B->port),
+ pkt->print_id(buf2,100,pkt->src_id,pkt->id_len), ntohs(A->port));
+ }else{
+ dbgprintf(1,"Half-connection from port %i to %i probably using CCID 2\n",
+ ntohs(B->port),ntohs(A->port));
+ }
+ }
+ }
+
+ /*NDP Count Option*/
+ if(*opt==37){
+ if(B->type==UNKNOWN){
+ B->type=CCID3;
+ if(pkt->print_id){
+ dbgprintf(1,"Half-connection from %s:%i to %s:%i probably using CCID 3\n",
+ pkt->print_id(buf1,100,pkt->dest_id,pkt->id_len),ntohs(B->port),
+ pkt->print_id(buf2,100,pkt->src_id,pkt->id_len), ntohs(A->port));
+ }else{
+ dbgprintf(1,"Half-connection from port %i to %i probably using CCID 3\n",
+ ntohs(B->port),ntohs(A->port));
+ }
+ }
+ }
+
+ /*Feature negotation*/
+ if(*opt==32){
+ /*Change L*/
+ if(!process_feature(opt+2,length-2,FALSE,TRUE,pkt,A,B)){
+ return 0;
+ }
+ }
+ if(*opt==33){
+ /*Confirm L*/
+ if(!process_feature(opt+2,length-2,TRUE,TRUE,pkt,A,B)){
+ return 0;
+ }
+ }
+ if(*opt==34){
+ /*Change R*/
+ if(!process_feature(opt+2,length-2,FALSE,FALSE,pkt,A,B)){
+ return 0;
+ }
+ }
+ if(*opt==35){
+ /*Confirm R*/
+ if(!process_feature(opt+2,length-2,TRUE,FALSE,pkt,A,B)){
+ return 0;
+ }
}
+
+ optlen-=length;
+ opt+=length;
}
-
- dbgprintf(1, "Error: Address Not Found! looking for: %X\n", num);
-return 0;
+
+ return 1;
}
+int process_feature(const u_char* feat, int len, int confirm, int L,
+ const struct const_packet* pkt, struct hcon* A, struct hcon* B)
+{
+ const u_char* val;
+ int ccid;
+ char buf1[100];
+ char buf2[100];
+
+ val=feat+1;
+
+ switch(*feat){
+ case 1:
+ /*CCID*/
+ if(confirm==TRUE){
+ switch(*val){
+ case 2:
+ ccid=CCID2;
+ break;
+ case 3:
+ ccid=CCID3;
+ break;
+ default:
+ ccid=UNKNOWN;
+ break;
+ }
+ if(L==TRUE){
+ B->type=ccid;
+ if(pkt->print_id){
+ dbgprintf(1,"Half-connection from %s:%i to %s:%i using CCID %i\n",
+ pkt->print_id(buf1,100,pkt->dest_id,pkt->id_len),ntohs(B->port),
+ pkt->print_id(buf2,100,pkt->src_id,pkt->id_len), ntohs(A->port), *val);
+ }else{
+ dbgprintf(1,"Half-connection from port %i to %i using CCID %i\n",
+ ntohs(B->port),ntohs(A->port), *val);
+ }
+ }else{
+ A->type=ccid;
+ if(pkt->print_id){
+ dbgprintf(1,"Half-connection from %s:%i to %s:%i using CCID %i\n",
+ pkt->print_id(buf1,100,pkt->src_id,pkt->id_len),ntohs(A->port),
+ pkt->print_id(buf2,100,pkt->dest_id,pkt->id_len), ntohs(B->port), *val);
+ }else{
+ dbgprintf(1,"Half-connection from port %i to %i using CCID %i\n",
+ ntohs(A->port),ntohs(B->port), *val);
+ }
+ }
+ }
+ break;
+ case 2:
+ /*Short sequence nums*/
+ if(confirm==TRUE && *val==1){
+ B->type=IGNORE;
+ A->type=IGNORE;
+ dbgprintf(0,"Error: DCCP is trying to turn on short sequence numbers\n"
+ " for the connection between %i and %i. We do not support this.\n"
+ " This connection will be ignored.",ntohs(A->port),ntohs(B->port));
+ return 0;
+ }
+ break;
+ }
+ return 1;
+}
/*Ack Vector to SACK Option*/
-void ack_vect2sack(struct host *seq, struct tcphdr *tcph, u_char* tcpopts, u_char* dccphdr, __be32 dccpack)
+void ack_vect2sack(struct hcon *hcn, struct tcphdr *tcph, u_char* tcpopts, u_char* dccphdr,
+ d_seq_num dccpack, struct hcon* o_hcn)
{
int hdrlen=((struct dccp_hdr*)dccphdr)->dccph_doff*4;
int optlen;
int len;
int tmp;
- __be32 bp;
+ d_seq_num bp;
u_char* temp;
u_char* opt;
u_char* cur;
int num_blocks;
int cont;
int isopt;
-
+
/*setup pointer to DCCP options and determine how long the options are*/
optlen=hdrlen-sizeof(struct dccp_hdr) - sizeof(struct dccp_hdr_ext) - sizeof(struct dccp_hdr_ack_bits);
opt=dccphdr + sizeof(struct dccp_hdr) + sizeof(struct dccp_hdr_ext) + sizeof(struct dccp_hdr_ack_bits);
+ if(optlen<=0){
+ return;
+ }
+
/*setup tcp pointers*/
num_blocks=4;
*tcpopts=5;
/*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;
if((*cur & 0xC0)==0xC0 || (*cur & 0xC0)==0x40){ //lost packet
if(cont){ /*end a SACK run, if one is started*/
- bR=convert_ack(seq, bp);
+ bR=convert_ack(hcn, bp,o_hcn);
cont=0;
num_blocks--;
*pR=htonl(bR);
tcph->doff+=2;
*tlen+=8;
pL=pR+1;
- pR=pL+1;
+ pR=pL+1;
}
bp= bp - (*cur & 0x3F)- 1;
}
-
+
if((*cur & 0xC0)==0x00){ //received packet
if(!cont){ /*if no SACK run and we can start another one, do so*/
if(num_blocks>0){
- bL=convert_ack(seq, bp);
+ bL=convert_ack(hcn, bp, o_hcn);
isopt=1;
cont=1;
cur++;
}
}
-
+
optlen-=len;
opt+=len;
}
/*if we are in the middle of a SACK run, close it*/
if(cont){
- bR=convert_ack(seq, bp);
+ bR=convert_ack(hcn, bp,o_hcn);
*pR=htonl(bR);
*pL=htonl(bL);
tcph->doff+=2;
return;
}
+void version()
+{
+ dbgprintf(0, "dccp2tcp version %.1f\n",DCCP2TCP_VERSION);
+ dbgprintf(0, "Copyright (C) %i Samuel Jero <sj323707@ohio.edu>\n",COPYRIGHT_YEAR);
+ dbgprintf(0, "This program comes with ABSOLUTELY NO WARRANTY.\n");
+ dbgprintf(0, "This is free software, and you are welcome to\n");
+ dbgprintf(0, "redistribute it under certain conditions.\n");
+ exit(0);
+}
+
+/*Usage information for program*/
+void usage()
+{
+ dbgprintf(0,"Usage: dccp2tcp [-v] [-h] [-V] [-y] [-g] [-s] dccp_file tcp_file\n");
+ dbgprintf(0, " -v verbose. May be repeated for additional verbosity.\n");
+ dbgprintf(0, " -V Version information\n");
+ dbgprintf(0, " -h Help\n");
+ dbgprintf(0, " -y Yellow line is highest ACK\n");
+ dbgprintf(0, " -g Green line is highest ACK\n");
+ dbgprintf(0, " -s convert ACK Vectors to SACKS\n");
+ exit(0);
+}
+
/*Debug Printf*/
void dbgprintf(int level, const char *fmt, ...)
{