]> sjero.net Git - dccp2tcp/commitdiff
Redesign Encapsulation System
authorSamuel Jero <sj323707@ohio.edu>
Mon, 16 May 2011 03:13:56 +0000 (23:13 -0400)
committerSamuel Jero <sj323707@ohio.edu>
Mon, 16 May 2011 03:13:56 +0000 (23:13 -0400)
Complete Redesign. Added Correct packet de-encapsulation by protocol fields.
Unsupported Protocols are ignored. Added SSL (Linux Cooked Capture) as link layer.

ChangeLog
Makefile
README
dccp2tcp.c
dccp2tcp.h
encap.c [new file with mode: 0644]
encap.h [new file with mode: 0644]

index 9ef0bff632c0ff9a0a8f1cc147fd1e02b259a1dc..4341700e36efd351c03055e83bfb1865484b6860 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+05/15/2011:
+       Release 1.3
+       Improvements:
+       1)Complete Redesign of Encapsulation system. It now examines each protocol layer and removes encapsulation correctly.
+               If a protocol is not supported, the packet is ignored. As of right now the supported protocols are:
+                +Ethernet
+                +Linux Cooked Capture (SLL)
+                +IPv4
+       
 02/01/2011:
        Release 1.2
        Bug Fixes:
index 5289c5185f4d99f23a8f6118fe98a6b8cfbed4eb..b4539fda78afe9e3735caefd9b0fd7a3bd5c9de5 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -28,7 +28,7 @@ dccp2tcp: dccp2tcp.o encap.o
 dccp2tcp.o: dccp2tcp.h dccp2tcp.c
        gcc ${CFLAGS} ${LDLIBS} --std=gnu99 -c dccp2tcp.c -odccp2tcp.o
 
-encap.o: encap.c dccp2tcp.h
+encap.o: encap.c dccp2tcp.h encap.h
        gcc ${CFLAGS} ${LDLIBS} --std=gnu99 -c encap.c -oencap.o
 
 install: dccp2tcp
diff --git a/README b/README
index 02c14972b3dfd03ff3227539ea820117f7b23382..2001e5c8137c29538698b3534e251c12058bb3fd 100644 (file)
--- a/README
+++ b/README
@@ -32,13 +32,13 @@ xplot a2b_tsg.xpl a2b_rtt.xpl
 
 
 This program does have several important limitations:
-       1)Supports only a single DCCP contection per capture.
+       1)Supports only a single DCCP connection per capture.
        2)Source Port can't equal Destination Port. If the two are equal, this program will get very confused.
        3)DCCP MUST use 48 bit sequence numbers.
        4)Checksums are not computed (they are zeroed).
        5)Only converts those packet types used by the Linux implementation at this date
        6)DCCP Ack packets show up as TCP packets containing one byte
-       7)Very little error checking of packet headers, it's research software afterall
+       7)Very little error checking of DCCP
 
 
 
index 193df2c46d678e21dfbff1dc1124a98b87fbd9a9..94bc7dd7bd1be7e78189cd978394a1124f6c7558 100644 (file)
@@ -1,7 +1,7 @@
 /******************************************************************************
 Author: Samuel Jero
 
-Date: 4/2011
+Date: 5/2011
 
 Description: Program to convert a DCCP flow to a TCP flow for DCCP analysis via
                tcptrace.
@@ -23,7 +23,7 @@ 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_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*/
@@ -33,7 +33,7 @@ struct seq_num        *s2;    /*sequence number structure for side two of connection*/
 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, u_char **ndata, int *nlength, const u_char **odata, int *length);
+int convert_packet(struct pcap_pkthdr *h, u_char **nptr, int *nlength, const u_char **optr, int *length);
 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 size, enum dccp_pkt_type type);
@@ -144,6 +144,10 @@ void handle_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *byte
        int                                     length;
        int                                     nlength;
        struct pcap_pkthdr      nh;
+       int                                     link_type;
+
+       /*Determine the link type for this packet*/
+       link_type=pcap_datalink(in);
 
        /*create new libpcap header*/
        memcpy(&nh, h, sizeof(struct pcap_pkthdr));
@@ -161,11 +165,8 @@ void handle_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *byte
        memset(nptr, 0, MAX_PACKET);
        
        /*do all the fancy conversions*/
-       if(eth_ip_encap_pre(&nh, &nptr, &nlength, &bytes, &length)<0){
-               return;
-       }
-       convert_packet(&nh, &nptr, &nlength, &bytes, &length);
-       if(eth_ip_encap_post(&nh, &ndata, &nlength)<0){
+       if(!do_encap(link_type, &nh, &nptr, &nlength, &bytes, &length)){
+               free(ndata);
                return;
        }
 
@@ -178,10 +179,10 @@ return;
 
 
 /*do all the dccp to tcp conversions*/
-void convert_packet(struct pcap_pkthdr *h, u_char **ndata, int *nlength, const u_char **odata, int *length)
+int convert_packet(struct pcap_pkthdr *h, u_char **nptr, int *nlength, const u_char **optr, int *length)
 {      
-       u_char* ncur=*ndata;
-       const u_char* ocur=*odata;
+       u_char* ncur=*nptr;
+       const u_char* ocur=*optr;
        struct tcphdr *tcph;
        struct dccp_hdr *dccph;
        struct dccp_hdr_ext *dccphex;
@@ -203,7 +204,7 @@ void convert_packet(struct pcap_pkthdr *h, u_char **ndata, int *nlength, const u
 
        /*determine data length*/
        datalength=*length - dccph->dccph_doff*4;
-       pd=*odata + dccph->dccph_doff*4;
+       pd=*optr + dccph->dccph_doff*4;
 
        /*set tcp standard features*/
        tcph->source=dccph->dccph_sport;
@@ -219,7 +220,7 @@ void convert_packet(struct pcap_pkthdr *h, u_char **ndata, int *nlength, const u
 
        /*Only accept the first connection*/
        if(s1 && s2 && dccph->dccph_sport!=s1->addr && dccph->dccph_dport!=s1->addr){
-               return;
+               return 0;
        }
 
        /*make changes by packet type*/
@@ -315,7 +316,7 @@ void convert_packet(struct pcap_pkthdr *h, u_char **ndata, int *nlength, const u
                tcph->rst=0;
 
                /*copy data*/
-               npd=*ndata + tcph->doff*4;
+               npd=*nptr + tcph->doff*4;
                memcpy(npd, pd, datalength);
 
                /*calculate length*/
@@ -538,11 +539,11 @@ void convert_packet(struct pcap_pkthdr *h, u_char **ndata, int *nlength, const u
 
        if(dccph->dccph_type==DCCP_PKT_INVALID){//DCCP INVALID----Never seen in packet capture
                dbgprintf(0,"Invalid DCCP Packet!!\n");
-               exit(1);
+               return 0;
        }
 
        *nlength=len;
-return;
+return 1;
 }
 
 
index 3395339bb82e0371a25cadf79eca2e2eed77e02c..151b22cb3a957943c3358370adbb917f41ce69cc 100644 (file)
@@ -1,7 +1,7 @@
 /******************************************************************************
 Author: Samuel Jero
 
-Date: 4/2011
+Date: 5/2011
 
 Description: Header file for program to convert a DCCP flow to a TCP flow for DCCP
                 analysis via tcptrace.
@@ -83,11 +83,7 @@ extern struct seq_num        *s2;    /*sequence number structure for side two of connectio
  */
 void dbgprintf(int level, const char *fmt, ...);
 
-/* Encapsulation functions*/
-int eth_ip_encap_pre(struct pcap_pkthdr *h, u_char **nptr, int *nlength, const u_char **optr, int *length);
-int eth_ip_encap_post(struct pcap_pkthdr *h, u_char** nptr, int *nlength);
-
-/*The Conversion Function*/
-void convert_packet(struct pcap_pkthdr *h, u_char **ndata, int *nlength, const u_char **odata, int *length);
+/*Function to parse encapsulation*/
+int do_encap(int link, struct pcap_pkthdr *h, u_char **nptr, int *nlength, const u_char **optr, int *length);
 
 #endif
diff --git a/encap.c b/encap.c
new file mode 100644 (file)
index 0000000..f5c4ea7
--- /dev/null
+++ b/encap.c
@@ -0,0 +1,220 @@
+/******************************************************************************
+Author: Samuel Jero
+
+Date: 5/2011
+
+Description: Encapsulation Functions for DCCP conversion to TCP
+
+******************************************************************************/
+#include "dccp2tcp.h"
+#include "encap.h"
+#include "pcap/sll.h"
+
+/*Encapsulation start point and link layer selector*/
+int do_encap(int link, struct pcap_pkthdr *h, u_char **nptr, int *nlength, const u_char **optr, int *length)
+{
+       switch(link){
+               case DLT_EN10MB:
+                               /*Ethernet*/
+                               if(!ethernet_encap(h, nptr, nlength, optr, length)){
+                                               return 0;
+                               }
+                               break;
+               case DLT_RAW:
+                               /*Raw. Just IP*/
+                               if(!ipv4_encap(h, nptr, nlength, optr, length)){
+                                               return 0;
+                               }
+                               break;
+               case DLT_LINUX_SLL:
+                               /*Linux Cooked Capture*/
+                               if(!linux_cooked_encap(h, nptr, nlength, optr, length)){
+                                       return 0;
+                               }
+                               break;
+               default:
+                               dbgprintf(0, "Unknown Link Layer\n");
+                               return 0;
+       }
+
+       /*Adjust libpcap header*/
+       if(h->caplen >= h->len || h->caplen >= *nlength){
+               h->caplen=*nlength;
+       }
+       h->len=*nlength;
+
+return 1;
+}
+
+/*Standard Ethernet Encapsulation*/
+int ethernet_encap(struct pcap_pkthdr *h, u_char **nptr, int *nlength, const u_char **optr, int *length)
+{
+               struct ether_header             *ethh;
+               int                                             next_len;
+               int                                             next_nlen;
+               u_char                                  *next_nptr;
+               const u_char                    *next_optr;
+
+               /*Safety checks*/
+               if(!h || !nptr || !nlength || !optr || !length || !*nptr || !*optr){
+                       dbgprintf(0,"Error: Ethernet Encapsulation Function given bad data!\n");
+                       return 0;
+               }
+               if(*length < sizeof(struct ether_header) || *nlength < sizeof(struct ether_header)){
+                       dbgprintf(0, "Error: Ethernet Encapsulation Function given packet of wrong size!\n");
+                       return 0;
+               }
+
+               /*Copy Ethernet header over*/
+               memcpy(*nptr, *optr, sizeof(struct ether_header));
+
+               /*Cast Pointer*/
+               ethh=(struct ether_header*)(*nptr);
+
+               /*Adjust pointers and lengths*/
+               next_optr= *optr+ sizeof(struct ether_header);
+               next_nptr= *nptr+ sizeof(struct ether_header);
+               next_len= *length- sizeof(struct ether_header);
+               next_nlen= *nlength- sizeof(struct ether_header);
+
+               /*Select Next Protocol*/
+               switch(ntohs(ethh->ether_type)){
+                       case ETHERTYPE_IP:
+                                       if(!ipv4_encap(h, &next_nptr, &next_nlen, &next_optr, &next_len)){
+                                                       return 0;
+                                       }
+                                       break;
+                       default:
+                                       dbgprintf(1, "Unknown Next Protocol at Ethernet\n");
+                                       return 0;
+                                       break;
+               }
+
+               /*Adjust length*/
+               *nlength=next_nlen + sizeof(struct ether_header);
+return 1;
+}
+
+/*IPv4 Encapsulation*/
+int ipv4_encap(struct pcap_pkthdr *h, u_char **nptr, int *nlength, const u_char **optr, int *length)
+{
+               struct iphdr                    *iph;
+               int                                             next_len;
+               int                                             next_nlen;
+               u_char                                  *next_nptr;
+               const u_char                    *next_optr;
+
+               /*Safety checks*/
+               if(!h || !nptr || !nlength || !optr || !length || !*nptr || !*optr){
+                       dbgprintf(0,"Error: IPv4 Encapsulation Function given bad data!\n");
+                       return 0;
+               }
+               if(*length < sizeof(struct iphdr) || *nlength < sizeof(struct iphdr)){
+                       dbgprintf(0, "Error: IPv4 Encapsulation Function given packet of wrong size!\n");
+                       return 0;
+               }
+
+               /*Copy IPv4 header over*/
+               memcpy(*nptr, *optr, sizeof(struct iphdr));
+
+               /*Cast Pointer*/
+               iph=(struct iphdr*)(*nptr);
+
+               /*Adjust pointers and lengths*/
+               next_optr= *optr +iph->ihl*4;
+               next_nptr= *nptr +iph->ihl*4;
+               next_len= *length -iph->ihl*4;
+               next_nlen= *nlength-iph->ihl*4;
+
+               /*Confirm that this is IPv4*/
+               if(iph->version!=4){
+                       dbgprintf(1, "Note: Packet is not IPv4\n");
+                       return 0;
+               }
+
+               /*Select Next Protocol*/
+               switch(iph->protocol){
+                       case 0x21:
+                                       /*DCCP*/
+                                       if(!convert_packet(h, &next_nptr, &next_nlen, &next_optr, &next_len)){
+                                               return 0;
+                                       }
+                                       break;
+                       default:
+                                       dbgprintf(1, "Unknown Next Protocol at IPv4\n");
+                                       return 0;
+                                       break;
+               }
+
+               /*set ip to indicate that TCP is next protocol*/
+               iph->protocol=6;
+               iph->check=htonl(0);
+
+               /*Adjust length*/
+               *nlength=next_nlen + iph->ihl*4;
+
+               /*Determine if computed length is reasonable*/
+               if(*nlength > 0xFFFF){
+                               dbgprintf(1, "Error: Given TCP header+data length is too large for an IPv4 packet!\n");
+                               return 0;
+               }
+
+               /*Adjust IPv4 header to account for packet's total length*/
+               iph->tot_len=htons(*nlength);
+return 1;
+}
+
+int linux_cooked_encap(struct pcap_pkthdr *h, u_char **nptr, int *nlength, const u_char **optr, int *length)
+{
+       struct sll_header       *slh;
+       int                                     next_len;
+       int                                     next_nlen;
+       u_char                          *next_nptr;
+       const u_char            *next_optr;
+
+
+       /*Safety checks*/
+       if(!h || !nptr || !nlength || !optr || !length || !*nptr || !*optr){
+               dbgprintf(0,"Error: SLL Encapsulation Function given bad data!\n");
+               return 0;
+       }
+       if(*length < sizeof(struct sll_header) || *nlength < sizeof(struct sll_header)){
+               dbgprintf(0, "Error: SLL Encapsulation Function given packet of wrong size!\n");
+               return 0;
+       }
+
+       /*Copy SLL header over*/
+       memcpy(*nptr, *optr, sizeof(struct sll_header));
+
+       /*Cast Pointer*/
+       slh=(struct sll_header*)(*nptr);
+
+       /*Adjust pointers and lengths*/
+       next_optr= *optr + sizeof(struct sll_header);
+       next_nptr= *nptr + sizeof(struct sll_header);
+       next_len= *length - sizeof(struct sll_header);
+       next_nlen= *nlength- sizeof(struct sll_header);
+
+       /*Confirm that this is SLL*/
+       if(ntohs(slh->sll_pkttype) > 4){
+               dbgprintf(1, "Note: Packet is not SLL (Linux Cooked Capture)\n");
+               return 0;
+       }
+
+       /*Select Next Protocol*/
+       switch(ntohs(slh->sll_protocol)){
+               case ETHERTYPE_IP:
+                               if(!ipv4_encap(h, &next_nptr, &next_nlen, &next_optr, &next_len)){
+                                               return 0;
+                               }
+                               break;
+               default:
+                               dbgprintf(1, "Unknown Next Protocol at SLL\n");
+                               return 0;
+                               break;
+       }
+
+       /*Adjust length*/
+       *nlength=next_nlen + sizeof(struct sll_header);
+return 1;
+}
diff --git a/encap.h b/encap.h
new file mode 100644 (file)
index 0000000..02aaccd
--- /dev/null
+++ b/encap.h
@@ -0,0 +1,48 @@
+/******************************************************************************
+Author: Samuel Jero
+
+Date: 5/2011
+
+Description: Header file for Encapsulation Functions for DCCP to TCP conversion
+
+******************************************************************************/
+#ifndef ENCAP_H_
+#define ENCAP_H_
+
+/*
+ * All Conversion functions use these standard arguments:
+ *  struct pcap_pkthdr *h: This is a copy of the libpcap packet structure.
+ *                                                You are free to modify and use the fields.
+ *
+ *  u_char **nptr:             This is a pointer to a buffer for the new packet.
+ *                                             Each encapsulation has the responsibility to call
+ *                                             When a function is called, this will point at the
+ *                                             location for that protocol's header to start.
+ *
+ *  int *nlength:              The length of the new packet. Each encapsulation
+ *                                     can rely on this to contain the remaining buffer
+ *                                     space AND must return with this parameter containing
+ *                                     the length of the new packet at that layer.
+ *
+ *  u_char** optr:             This is a pointer to the buffer containing the
+ *                                     old packet. When a functio is called, this will
+ *                                     point at the location of that protocol's header.
+ *
+ *  int* length:               The length of the old packet. Each encapsulation
+ *                                     layer MUST decrement this by the amount of it's
+ *                                     headers. An encapsulation layer MUST never read
+ *                                     beyond this into optr.
+ */
+
+/*
+ * Last Level Conversion Function
+ * Converts DCCP to TCP for analysis by TCPTRACE
+ */
+int convert_packet(struct pcap_pkthdr *h, u_char **nptr, int *nlength, const u_char **optr, int *length);
+
+/*Standard Encapsulation Functions*/
+int ethernet_encap(struct pcap_pkthdr *h, u_char **nptr, int *nlength, const u_char **optr, int *length);
+int linux_cooked_encap(struct pcap_pkthdr *h, u_char **nptr, int *nlength, const u_char **optr, int *length);
+int ipv4_encap(struct pcap_pkthdr *h, u_char **nptr, int *nlength, const u_char **optr, int *length);
+
+#endif /* ENCAP_H_ */