From 1237fc38571cb93646caadeaf168b4445cf2b288 Mon Sep 17 00:00:00 2001 From: Samuel Jero Date: Sun, 15 May 2011 23:13:56 -0400 Subject: [PATCH] Redesign Encapsulation System Complete Redesign. Added Correct packet de-encapsulation by protocol fields. Unsupported Protocols are ignored. Added SSL (Linux Cooked Capture) as link layer. --- ChangeLog | 9 +++ Makefile | 2 +- README | 4 +- dccp2tcp.c | 33 ++++---- dccp2tcp.h | 10 +-- encap.c | 220 +++++++++++++++++++++++++++++++++++++++++++++++++++++ encap.h | 48 ++++++++++++ 7 files changed, 300 insertions(+), 26 deletions(-) create mode 100644 encap.c create mode 100644 encap.h diff --git a/ChangeLog b/ChangeLog index 9ef0bff..4341700 100644 --- 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: diff --git a/Makefile b/Makefile index 5289c51..b4539fd 100644 --- 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 02c1497..2001e5c 100644 --- 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 diff --git a/dccp2tcp.c b/dccp2tcp.c index 193df2c..94bc7dd 100644 --- a/dccp2tcp.c +++ b/dccp2tcp.c @@ -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; } diff --git a/dccp2tcp.h b/dccp2tcp.h index 3395339..151b22c 100644 --- a/dccp2tcp.h +++ b/dccp2tcp.h @@ -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 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 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_ */ -- 2.39.2