/******************************************************************************
-Author: Samuel Jero
+Utility to convert a DCCP flow to a TCP flow for DCCP analysis via
+ tcptrace. Encapsulation Functions for DCCP conversion to TCP.
-Date: 7/2011
+Copyright (C) 2012 Samuel Jero <sj323707@ohio.edu>
-Description: Encapsulation Functions for DCCP conversion to TCP
+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: 11/2012
******************************************************************************/
#include "dccp2tcp.h"
#include "encap.h"
-#include "pcap/sll.h"
+#include "checksums.h"
+#include <pcap/sll.h>
+#include <netinet/ip6.h>
+#include <netdb.h>
/*Encapsulation start point and link layer selector*/
int do_encap(int link, struct packet *new, const struct const_packet *old)
nnew.length= new->length - sizeof(struct ether_header);
nnew.h=new->h;
nold.h=old->h;
+ nnew.print_id=NULL;
+ nnew.dest_id=NULL;
+ nnew.src_id=NULL;
+ nnew.id_len=0;
+ nold.print_id=NULL;
+ nold.dest_id=NULL;
+ nold.src_id=NULL;
+ nold.id_len=0;
/*Select Next Protocol*/
switch(ntohs(ethh->ether_type)){
return 0;
}
break;
+ case ETHERTYPE_IPV6:
+ if(!ipv6_encap(&nnew, &nold)){
+ return 0;
+ }
+ break;
default:
dbgprintf(1, "Unknown Next Protocol at Ethernet\n");
return 0;
return 1;
}
+/*IPv6 Encapsulation*/
+int ipv6_encap(struct packet *new, const struct const_packet *old)
+{
+ struct ip6_hdr *iph;
+ struct packet nnew;
+ struct const_packet nold;
+
+ /*Safety checks*/
+ if(!new || !old || !new->data || !old->data || !new->h || !old->h){
+ dbgprintf(0,"Error: IPv6 Encapsulation Function given bad data!\n");
+ return 0;
+ }
+ if(old->length < sizeof(struct ip6_hdr) || new->length < sizeof(struct ip6_hdr)){
+ dbgprintf(0, "Error: IPv6 Encapsulation Function given packet of wrong size!\n");
+ return 0;
+ }
+
+ /*Copy IPv6 header over*/
+ memcpy(new->data, old->data, sizeof(struct ip6_hdr));
+
+ /*Cast Pointer*/
+ iph=(struct ip6_hdr*)(new->data);
+
+ /*Adjust pointers and lengths*/
+ nold.data= old->data + sizeof(struct ip6_hdr);
+ nnew.data= new->data +sizeof(struct ip6_hdr);
+ nold.length= old->length - sizeof(struct ip6_hdr);
+ nnew.length= new->length - sizeof(struct ip6_hdr);
+ nnew.h=new->h;
+ nold.h=old->h;
+ nnew.print_id=print_ipv6;
+ nold.print_id=print_ipv6;
+ nnew.id_len=16;
+ nold.id_len=16;
+
+ /*Confirm that this is IPv6*/
+ if((ntohl(iph->ip6_ctlun.ip6_un1.ip6_un1_flow) & (0xF0000000)) == (60000000)){
+ dbgprintf(1, "Note: Packet is not IPv6\n");
+ return 0;
+ }
+
+ /*Select Next Protocol*/
+ switch(iph->ip6_ctlun.ip6_un1.ip6_un1_nxt){
+ case 33:
+ /*DCCP*/
+ nnew.src_id=malloc(nnew.id_len);
+ nnew.dest_id=malloc(nnew.id_len);
+ nold.src_id=malloc(nold.id_len);
+ nold.dest_id=malloc(nold.id_len);
+ if(nnew.src_id==NULL||nnew.dest_id==NULL ||
+ nold.src_id==NULL||nold.dest_id==NULL){
+ dbgprintf(0,"Error: Couldn't allocate Memory\n");
+ exit(1);
+ }
+ memcpy(nnew.src_id,&iph->ip6_src,nnew.id_len);
+ memcpy(nnew.dest_id,&iph->ip6_dst,nnew.id_len);
+ memcpy(nold.src_id,&iph->ip6_src,nold.id_len);
+ memcpy(nold.dest_id,&iph->ip6_dst,nold.id_len);
+ if(!convert_packet(&nnew, &nold)){
+ return 0;
+ }
+ break;
+ default:
+ dbgprintf(1, "Unknown Next Protocol at IPv6\n");
+ return 0;
+ break;
+ }
+
+ /*set ip to indicate that TCP is next protocol*/
+ iph->ip6_ctlun.ip6_un1.ip6_un1_nxt=6;
+
+ /*Determine if computed length is reasonable*/
+ if(nnew.length > 0xFFFF){
+ dbgprintf(1, "Error: Given TCP data length is too large for an IPv6 packet!\n");
+ return 0;
+ }
+
+ /*Adjust IPv6 header to account for packet's total length*/
+ iph->ip6_ctlun.ip6_un1.ip6_un1_plen=htons(nnew.length);
+
+ /*Adjust length*/
+ new->length=nnew.length + sizeof(struct ip6_hdr);
+
+ /*Cleanup*/
+ free(nnew.dest_id);
+ free(nnew.src_id);
+ free(nold.dest_id);
+ free(nold.src_id);
+return 1;
+}
+
/*IPv4 Encapsulation*/
int ipv4_encap(struct packet *new, const struct const_packet *old)
{
nnew.length= new->length -iph->ihl*4;
nnew.h=new->h;
nold.h=old->h;
+ nnew.print_id=print_ipv4;
+ nold.print_id=print_ipv4;
+ nnew.id_len=4;
+ nold.id_len=4;
/*Confirm that this is IPv4*/
if(iph->version!=4){
/*Select Next Protocol*/
switch(iph->protocol){
- case 0x21:
+ case 33:
/*DCCP*/
- nnew.src_id=iph->saddr;
- nnew.dest_id=iph->daddr;
+ nnew.src_id=malloc(nnew.id_len);
+ nnew.dest_id=malloc(nnew.id_len);
+ nold.src_id=malloc(nold.id_len);
+ nold.dest_id=malloc(nold.id_len);
+ if(nnew.src_id==NULL||nnew.dest_id==NULL||
+ nold.src_id==NULL||nold.dest_id==NULL){
+ dbgprintf(0,"Error: Couldn't allocate Memory\n");
+ exit(1);
+ }
+ memcpy(nnew.src_id,&iph->saddr,nnew.id_len);
+ memcpy(nnew.dest_id,&iph->daddr,nnew.id_len);
+ memcpy(nold.src_id,&iph->saddr,nold.id_len);
+ memcpy(nold.dest_id,&iph->daddr,nold.id_len);
if(!convert_packet(&nnew, &nold)){
return 0;
}
/*Adjust IPv4 header to account for packet's total length*/
iph->tot_len=htons(new->length);
+
+ /*Compute IPv4 Checksum*/
+ iph->check=0;
+ iph->check=ipv4_chksum(new->data,iph->ihl*4);
+
+ /*Cleanup*/
+ free(nnew.src_id);
+ free(nnew.dest_id);
+ free(nold.src_id);
+ free(nold.dest_id);
return 1;
}
nnew.length= new->length- sizeof(struct sll_header);
nnew.h=new->h;
nold.h=old->h;
+ nnew.print_id=NULL;
+ nnew.dest_id=NULL;
+ nnew.src_id=NULL;
+ nnew.id_len=0;
+ nold.print_id=NULL;
+ nold.dest_id=NULL;
+ nold.src_id=NULL;
+ nold.id_len=0;
/*Confirm that this is SLL*/
if(ntohs(slh->sll_pkttype) > 4){
return 0;
}
break;
+ case ETHERTYPE_IPV6:
+ if(!ipv6_encap(&nnew, &nold)){
+ return 0;
+ }
+ break;
default:
dbgprintf(1, "Unknown Next Protocol at SLL\n");
return 0;
new->length=nnew.length + sizeof(struct sll_header);
return 1;
}
+
+
+char *print_ipv6(char* buf, int len, u_char* id, int id_len)
+{
+ struct sockaddr_in6 sa;
+
+ if(buf==NULL){
+ return NULL;
+ }
+
+ memcpy(&sa.sin6_addr, id, id_len);
+ sa.sin6_family=AF_INET6;
+ if(getnameinfo((struct sockaddr*)&sa, sizeof(struct sockaddr_in6),
+ buf, len, NULL,0,NI_NUMERICHOST)<0){
+ return NULL;
+ }
+ return buf;
+}
+
+char *print_ipv4(char* buf, int len, u_char* id, int id_len)
+{
+ struct sockaddr_in sa;
+
+ if(buf==NULL){
+ return NULL;
+ }
+
+ memcpy(&sa.sin_addr, id, id_len);
+ sa.sin_family=AF_INET;
+ if(getnameinfo((struct sockaddr*)&sa, sizeof(struct sockaddr_in),
+ buf, len, NULL,0,NI_NUMERICHOST)<0){
+ return NULL;
+ }
+ return buf;
+}