X-Git-Url: http://sjero.net/git/?a=blobdiff_plain;f=encap.c;h=d2c06b1b44b98ce80131ef7fb2f87b7545141ac4;hb=5e3bc5722d048a5b9581cbe27c64de5048d444b0;hp=736cf3a3d06c3684dc757fe309c6aa9a23baa602;hpb=26f999e14172938ed30c0f365dc5d6be9f6ed09b;p=dccp2tcp diff --git a/encap.c b/encap.c index 736cf3a..d2c06b1 100644 --- a/encap.c +++ b/encap.c @@ -1,14 +1,32 @@ /****************************************************************************** -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: 11/2011 +Copyright (C) 2012 Samuel Jero -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 . + +Author: Samuel Jero +Date: 11/2012 ******************************************************************************/ #include "dccp2tcp.h" #include "encap.h" -#include "pcap/sll.h" +#include "checksums.h" +#include +#include +#include +#include /*Encapsulation start point and link layer selector*/ int do_encap(int link, struct packet *new, const struct const_packet *old) @@ -76,6 +94,14 @@ int ethernet_encap(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)){ @@ -84,6 +110,16 @@ int ethernet_encap(struct packet *new, const struct const_packet *old) return 0; } break; + case ETHERTYPE_IPV6: + if(!ipv6_encap(&nnew, &nold)){ + return 0; + } + break; + case ETHERTYPE_VLAN: + if(!ethernet_vlan_encap(&nnew, &nold)){ + return 0; + } + break; default: dbgprintf(1, "Unknown Next Protocol at Ethernet\n"); return 0; @@ -95,6 +131,164 @@ int ethernet_encap(struct packet *new, const struct const_packet *old) return 1; } +/*Ethernet 802.1Q VLAN Encapsulation*/ +int ethernet_vlan_encap(struct packet *new, const struct const_packet *old) +{ + struct vlan_tag *tag; + struct const_packet nold; + struct packet nnew; + + /*Safety checks*/ + if(!new || !old || !new->data || !old->data || !new->h || !old->h){ + dbgprintf(0,"Error: Ethernet VLAN Encapsulation Function given bad data!\n"); + return 0; + } + if(old->length < sizeof(struct vlan_tag) || new->length < sizeof(struct vlan_tag)){ + dbgprintf(0, "Error: Ethernet VLAN Encapsulation Function given packet of wrong size!\n"); + return 0; + } + + /*Copy VLAN tag over*/ + memcpy(new->data, old->data, sizeof(struct vlan_tag)); + + /*Cast Pointer*/ + tag=(struct vlan_tag*)(new->data); + + /*Adjust pointers and lengths*/ + nold.data= old->data+ sizeof(struct vlan_tag); + nnew.data= new->data + sizeof(struct vlan_tag); + nold.length= old->length - sizeof(struct vlan_tag); + nnew.length= new->length - sizeof(struct vlan_tag); + 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(tag->vlan_tci)){ + case ETHERTYPE_IP: + if(!ipv4_encap(&nnew, &nold)){ + return 0; + } + break; + case ETHERTYPE_IPV6: + if(!ipv6_encap(&nnew, &nold)){ + return 0; + } + break; + case ETHERTYPE_VLAN: + if(!ethernet_vlan_encap(&nnew, &nold)){ + return 0; + } + break; + default: + dbgprintf(1, "Unknown Next Protocol at Ethernet VLAN tag\n"); + return 0; + break; + } + + /*Adjust length*/ + new->length=nnew.length + sizeof(struct vlan_tag); +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) { @@ -125,6 +319,10 @@ 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){ @@ -134,10 +332,21 @@ int ipv4_encap(struct packet *new, const struct const_packet *old) /*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; } @@ -163,6 +372,16 @@ int ipv4_encap(struct packet *new, const struct const_packet *old) /*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; } @@ -196,6 +415,14 @@ int linux_cooked_encap(struct packet *new, const struct const_packet *old) 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){ @@ -210,6 +437,11 @@ int linux_cooked_encap(struct packet *new, const struct const_packet *old) 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; @@ -220,3 +452,38 @@ int linux_cooked_encap(struct packet *new, const struct const_packet *old) 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; +}