1 /******************************************************************************
2 Utility to convert a DCCP flow to a TCP flow for DCCP analysis via
3 tcptrace. Encapsulation Functions for DCCP conversion to TCP.
5 Copyright (C) 2012 Samuel Jero <sj323707@ohio.edu>
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 Author: Samuel Jero <sj323707@ohio.edu>
22 ******************************************************************************/
25 #include "checksums.h"
27 #include <netinet/ip6.h>
30 /*Encapsulation start point and link layer selector*/
31 int do_encap(int link, struct packet *new, const struct const_packet *old)
36 if(!ethernet_encap(new, old)){
42 if(!ipv4_encap(new, old)){
47 /*Linux Cooked Capture*/
48 if(!linux_cooked_encap(new, old)){
53 dbgprintf(0, "Unknown Link Layer\n");
57 /*Adjust libpcap header*/
58 if(new->h->caplen >= new->h->len || new->h->caplen >= new->length){
59 new->h->caplen=new->length;
61 new->h->len=new->length;
66 /*Standard Ethernet Encapsulation*/
67 int ethernet_encap(struct packet *new, const struct const_packet *old)
69 struct ether_header *ethh;
70 struct const_packet nold;
74 if(!new || !old || !new->data || !old->data || !new->h || !old->h){
75 dbgprintf(0,"Error: Ethernet Encapsulation Function given bad data!\n");
78 if(old->length < sizeof(struct ether_header) || new->length < sizeof(struct ether_header)){
79 dbgprintf(0, "Error: Ethernet Encapsulation Function given packet of wrong size!\n");
83 /*Copy Ethernet header over*/
84 memcpy(new->data, old->data, sizeof(struct ether_header));
87 ethh=(struct ether_header*)(new->data);
89 /*Adjust pointers and lengths*/
90 nold.data= old->data+ sizeof(struct ether_header);
91 nnew.data= new->data + sizeof(struct ether_header);
92 nold.length= old->length - sizeof(struct ether_header);
93 nnew.length= new->length - sizeof(struct ether_header);
105 /*Select Next Protocol*/
106 switch(ntohs(ethh->ether_type)){
108 if(!ipv4_encap(&nnew, &nold)){
113 if(!ipv6_encap(&nnew, &nold)){
118 dbgprintf(1, "Unknown Next Protocol at Ethernet\n");
124 new->length=nnew.length + sizeof(struct ether_header);
128 /*IPv6 Encapsulation*/
129 int ipv6_encap(struct packet *new, const struct const_packet *old)
133 struct const_packet nold;
136 if(!new || !old || !new->data || !old->data || !new->h || !old->h){
137 dbgprintf(0,"Error: IPv6 Encapsulation Function given bad data!\n");
140 if(old->length < sizeof(struct ip6_hdr) || new->length < sizeof(struct ip6_hdr)){
141 dbgprintf(0, "Error: IPv6 Encapsulation Function given packet of wrong size!\n");
145 /*Copy IPv6 header over*/
146 memcpy(new->data, old->data, sizeof(struct ip6_hdr));
149 iph=(struct ip6_hdr*)(new->data);
151 /*Adjust pointers and lengths*/
152 nold.data= old->data + sizeof(struct ip6_hdr);
153 nnew.data= new->data +sizeof(struct ip6_hdr);
154 nold.length= old->length - sizeof(struct ip6_hdr);
155 nnew.length= new->length - sizeof(struct ip6_hdr);
158 nnew.print_id=print_ipv6;
159 nold.print_id=print_ipv6;
163 /*Confirm that this is IPv6*/
164 if((ntohl(iph->ip6_ctlun.ip6_un1.ip6_un1_flow) & (0xF0000000)) == (60000000)){
165 dbgprintf(1, "Note: Packet is not IPv6\n");
169 /*Select Next Protocol*/
170 switch(iph->ip6_ctlun.ip6_un1.ip6_un1_nxt){
173 nnew.src_id=malloc(nnew.id_len);
174 nnew.dest_id=malloc(nnew.id_len);
175 nold.src_id=malloc(nold.id_len);
176 nold.dest_id=malloc(nold.id_len);
177 if(nnew.src_id==NULL||nnew.dest_id==NULL ||
178 nold.src_id==NULL||nold.dest_id==NULL){
179 dbgprintf(0,"Error: Couldn't allocate Memory\n");
182 memcpy(nnew.src_id,&iph->ip6_src,nnew.id_len);
183 memcpy(nnew.dest_id,&iph->ip6_dst,nnew.id_len);
184 memcpy(nold.src_id,&iph->ip6_src,nold.id_len);
185 memcpy(nold.dest_id,&iph->ip6_dst,nold.id_len);
186 if(!convert_packet(&nnew, &nold)){
191 dbgprintf(1, "Unknown Next Protocol at IPv6\n");
196 /*set ip to indicate that TCP is next protocol*/
197 iph->ip6_ctlun.ip6_un1.ip6_un1_nxt=6;
199 /*Determine if computed length is reasonable*/
200 if(nnew.length > 0xFFFF){
201 dbgprintf(1, "Error: Given TCP data length is too large for an IPv6 packet!\n");
205 /*Adjust IPv6 header to account for packet's total length*/
206 iph->ip6_ctlun.ip6_un1.ip6_un1_plen=htons(nnew.length);
209 new->length=nnew.length + sizeof(struct ip6_hdr);
219 /*IPv4 Encapsulation*/
220 int ipv4_encap(struct packet *new, const struct const_packet *old)
224 struct const_packet nold;
227 if(!new || !old || !new->data || !old->data || !new->h || !old->h){
228 dbgprintf(0,"Error: IPv4 Encapsulation Function given bad data!\n");
231 if(old->length < sizeof(struct iphdr) || new->length < sizeof(struct iphdr)){
232 dbgprintf(0, "Error: IPv4 Encapsulation Function given packet of wrong size!\n");
236 /*Copy IPv4 header over*/
237 memcpy(new->data, old->data, sizeof(struct iphdr));
240 iph=(struct iphdr*)(new->data);
242 /*Adjust pointers and lengths*/
243 nold.data= old->data +iph->ihl*4;
244 nnew.data= new->data +iph->ihl*4;
245 nold.length= old->length -iph->ihl*4;
246 nnew.length= new->length -iph->ihl*4;
249 nnew.print_id=print_ipv4;
250 nold.print_id=print_ipv4;
254 /*Confirm that this is IPv4*/
256 dbgprintf(1, "Note: Packet is not IPv4\n");
260 /*Select Next Protocol*/
261 switch(iph->protocol){
264 nnew.src_id=malloc(nnew.id_len);
265 nnew.dest_id=malloc(nnew.id_len);
266 nold.src_id=malloc(nold.id_len);
267 nold.dest_id=malloc(nold.id_len);
268 if(nnew.src_id==NULL||nnew.dest_id==NULL||
269 nold.src_id==NULL||nold.dest_id==NULL){
270 dbgprintf(0,"Error: Couldn't allocate Memory\n");
273 memcpy(nnew.src_id,&iph->saddr,nnew.id_len);
274 memcpy(nnew.dest_id,&iph->daddr,nnew.id_len);
275 memcpy(nold.src_id,&iph->saddr,nold.id_len);
276 memcpy(nold.dest_id,&iph->daddr,nold.id_len);
277 if(!convert_packet(&nnew, &nold)){
282 dbgprintf(1, "Unknown Next Protocol at IPv4\n");
287 /*set ip to indicate that TCP is next protocol*/
292 new->length=nnew.length + iph->ihl*4;
294 /*Determine if computed length is reasonable*/
295 if(nnew.length > 0xFFFF){
296 dbgprintf(1, "Error: Given TCP header+data length is too large for an IPv4 packet!\n");
300 /*Adjust IPv4 header to account for packet's total length*/
301 iph->tot_len=htons(new->length);
303 /*Compute IPv4 Checksum*/
305 iph->check=ipv4_chksum(new->data,iph->ihl*4);
315 int linux_cooked_encap(struct packet *new, const struct const_packet *old)
317 struct sll_header *slh;
319 struct const_packet nold;
323 if(!new|| !old || !new->data || !old->data || !new->h || !old->h){
324 dbgprintf(0,"Error: SLL Encapsulation Function given bad data!\n");
327 if(old->length < sizeof(struct sll_header) || new->length < sizeof(struct sll_header)){
328 dbgprintf(0, "Error: SLL Encapsulation Function given packet of wrong size!\n");
332 /*Copy SLL header over*/
333 memcpy(new->data, old->data, sizeof(struct sll_header));
336 slh=(struct sll_header*)(new->data);
338 /*Adjust pointers and lengths*/
339 nold.data= old->data + sizeof(struct sll_header);
340 nnew.data= new->data + sizeof(struct sll_header);
341 nold.length= old->length - sizeof(struct sll_header);
342 nnew.length= new->length- sizeof(struct sll_header);
354 /*Confirm that this is SLL*/
355 if(ntohs(slh->sll_pkttype) > 4){
356 dbgprintf(1, "Note: Packet is not SLL (Linux Cooked Capture)\n");
360 /*Select Next Protocol*/
361 switch(ntohs(slh->sll_protocol)){
363 if(!ipv4_encap(&nnew, &nold)){
368 if(!ipv6_encap(&nnew, &nold)){
373 dbgprintf(1, "Unknown Next Protocol at SLL\n");
379 new->length=nnew.length + sizeof(struct sll_header);
384 char *print_ipv6(char* buf, int len, u_char* id, int id_len)
386 struct sockaddr_in6 sa;
392 memcpy(&sa.sin6_addr, id, id_len);
393 sa.sin6_family=AF_INET6;
394 if(getnameinfo((struct sockaddr*)&sa, sizeof(struct sockaddr_in6),
395 buf, len, NULL,0,NI_NUMERICHOST)<0){
401 char *print_ipv4(char* buf, int len, u_char* id, int id_len)
403 struct sockaddr_in sa;
409 memcpy(&sa.sin_addr, id, id_len);
410 sa.sin_family=AF_INET;
411 if(getnameinfo((struct sockaddr*)&sa, sizeof(struct sockaddr_in),
412 buf, len, NULL,0,NI_NUMERICHOST)<0){