]> sjero.net Git - dccp2tcp/blob - encap.c
6f79307afd811ecf235c499385065e81edefb2c8
[dccp2tcp] / encap.c
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.
4
5 Copyright (C) 2012  Samuel Jero <sj323707@ohio.edu>
6
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.
11
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.
16
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/>.
19
20 Author: Samuel Jero <sj323707@ohio.edu>
21 Date: 11/2012
22 ******************************************************************************/
23 #include "dccp2tcp.h"
24 #include "encap.h"
25 #include "checksums.h"
26 #include <pcap/sll.h>
27 #include <netinet/ip6.h>
28 #include <netdb.h>
29
30 /*Encapsulation start point and link layer selector*/
31 int do_encap(int link, struct packet *new, const struct const_packet *old)
32 {
33         switch(link){
34                 case DLT_EN10MB:
35                                 /*Ethernet*/
36                                 if(!ethernet_encap(new, old)){
37                                                 return 0;
38                                 }
39                                 break;
40                 case DLT_RAW:
41                                 /*Raw. Just IP*/
42                                 if(!ipv4_encap(new, old)){
43                                                 return 0;
44                                 }
45                                 break;
46                 case DLT_LINUX_SLL:
47                                 /*Linux Cooked Capture*/
48                                 if(!linux_cooked_encap(new, old)){
49                                         return 0;
50                                 }
51                                 break;
52                 default:
53                                 dbgprintf(0, "Unknown Link Layer\n");
54                                 return 0;
55         }
56
57         /*Adjust libpcap header*/
58         if(new->h->caplen >= new->h->len || new->h->caplen >= new->length){
59                 new->h->caplen=new->length;
60         }
61         new->h->len=new->length;
62
63 return 1;
64 }
65
66 /*Standard Ethernet Encapsulation*/
67 int ethernet_encap(struct packet *new, const struct const_packet *old)
68 {
69                 struct ether_header     *ethh;
70                 struct const_packet nold;
71                 struct packet           nnew;
72
73                 /*Safety checks*/
74                 if(!new || !old || !new->data || !old->data || !new->h || !old->h){
75                         dbgprintf(0,"Error: Ethernet Encapsulation Function given bad data!\n");
76                         return 0;
77                 }
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");
80                         return 0;
81                 }
82
83                 /*Copy Ethernet header over*/
84                 memcpy(new->data, old->data, sizeof(struct ether_header));
85
86                 /*Cast Pointer*/
87                 ethh=(struct ether_header*)(new->data);
88
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);
94                 nnew.h=new->h;
95                 nold.h=old->h;
96                 nnew.print_id=NULL;
97                 nnew.dest_id=NULL;
98                 nnew.src_id=NULL;
99                 nnew.id_len=0;
100                 nold.print_id=NULL;
101                 nold.dest_id=NULL;
102                 nold.src_id=NULL;
103                 nold.id_len=0;
104
105                 /*Select Next Protocol*/
106                 switch(ntohs(ethh->ether_type)){
107                         case ETHERTYPE_IP:
108                                         if(!ipv4_encap(&nnew, &nold)){
109                                                         return 0;
110                                         }
111                                         break;
112                         case ETHERTYPE_IPV6:
113                                         if(!ipv6_encap(&nnew, &nold)){
114                                                         return 0;
115                                         }
116                                         break;
117                         default:
118                                         dbgprintf(1, "Unknown Next Protocol at Ethernet\n");
119                                         return 0;
120                                         break;
121                 }
122
123                 /*Adjust length*/
124                 new->length=nnew.length + sizeof(struct ether_header);
125 return 1;
126 }
127
128 /*IPv6 Encapsulation*/
129 int ipv6_encap(struct packet *new, const struct const_packet *old)
130 {
131                 struct ip6_hdr          *iph;
132                 struct packet           nnew;
133                 struct const_packet     nold;
134
135                 /*Safety checks*/
136                 if(!new || !old || !new->data || !old->data || !new->h || !old->h){
137                         dbgprintf(0,"Error: IPv6 Encapsulation Function given bad data!\n");
138                         return 0;
139                 }
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");
142                         return 0;
143                 }
144
145                 /*Copy IPv6 header over*/
146                 memcpy(new->data, old->data, sizeof(struct ip6_hdr));
147
148                 /*Cast Pointer*/
149                 iph=(struct ip6_hdr*)(new->data);
150
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);
156                 nnew.h=new->h;
157                 nold.h=old->h;
158                 nnew.print_id=print_ipv6;
159                 nold.print_id=print_ipv6;
160                 nnew.id_len=16;
161                 nold.id_len=16;
162
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");
166                         return 0;
167                 }
168
169                 /*Select Next Protocol*/
170                 switch(iph->ip6_ctlun.ip6_un1.ip6_un1_nxt){
171                         case 33:
172                                         /*DCCP*/
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");
180                                                 exit(1);
181                                         }
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)){
187                                                 return 0;
188                                         }
189                                         break;
190                         default:
191                                         dbgprintf(1, "Unknown Next Protocol at IPv6\n");
192                                         return 0;
193                                         break;
194                 }
195
196                 /*set ip to indicate that TCP is next protocol*/
197                 iph->ip6_ctlun.ip6_un1.ip6_un1_nxt=6;
198
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");
202                                 return 0;
203                 }
204
205                 /*Adjust IPv6 header to account for packet's total length*/
206                 iph->ip6_ctlun.ip6_un1.ip6_un1_plen=htons(nnew.length);
207
208                 /*Adjust length*/
209                 new->length=nnew.length + sizeof(struct ip6_hdr);
210
211                 /*Cleanup*/
212                 free(nnew.dest_id);
213                 free(nnew.src_id);
214                 free(nold.dest_id);
215                 free(nold.src_id);
216 return 1;
217 }
218
219 /*IPv4 Encapsulation*/
220 int ipv4_encap(struct packet *new, const struct const_packet *old)
221 {
222                 struct iphdr            *iph;
223                 struct packet           nnew;
224                 struct const_packet     nold;
225
226                 /*Safety checks*/
227                 if(!new || !old || !new->data || !old->data || !new->h || !old->h){
228                         dbgprintf(0,"Error: IPv4 Encapsulation Function given bad data!\n");
229                         return 0;
230                 }
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");
233                         return 0;
234                 }
235
236                 /*Copy IPv4 header over*/
237                 memcpy(new->data, old->data, sizeof(struct iphdr));
238
239                 /*Cast Pointer*/
240                 iph=(struct iphdr*)(new->data);
241
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;
247                 nnew.h=new->h;
248                 nold.h=old->h;
249                 nnew.print_id=print_ipv4;
250                 nold.print_id=print_ipv4;
251                 nnew.id_len=4;
252                 nold.id_len=4;
253
254                 /*Confirm that this is IPv4*/
255                 if(iph->version!=4){
256                         dbgprintf(1, "Note: Packet is not IPv4\n");
257                         return 0;
258                 }
259
260                 /*Select Next Protocol*/
261                 switch(iph->protocol){
262                         case 33:
263                                         /*DCCP*/
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");
271                                                 exit(1);
272                                         }
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)){
278                                                 return 0;
279                                         }
280                                         break;
281                         default:
282                                         dbgprintf(1, "Unknown Next Protocol at IPv4\n");
283                                         return 0;
284                                         break;
285                 }
286
287                 /*set ip to indicate that TCP is next protocol*/
288                 iph->protocol=6;
289                 iph->check=htonl(0);
290
291                 /*Adjust length*/
292                 new->length=nnew.length + iph->ihl*4;
293
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");
297                                 return 0;
298                 }
299
300                 /*Adjust IPv4 header to account for packet's total length*/
301                 iph->tot_len=htons(new->length);
302
303                 /*Compute IPv4 Checksum*/
304                 iph->check=0;
305                 iph->check=ipv4_chksum(new->data,iph->ihl*4);
306
307                 /*Cleanup*/
308                 free(nnew.src_id);
309                 free(nnew.dest_id);
310                 free(nold.src_id);
311                 free(nold.dest_id);
312 return 1;
313 }
314
315 int linux_cooked_encap(struct packet *new, const struct const_packet *old)
316 {
317         struct sll_header               *slh;
318         struct packet                   nnew;
319         struct const_packet             nold;
320
321
322         /*Safety checks*/
323         if(!new|| !old || !new->data || !old->data || !new->h || !old->h){
324                 dbgprintf(0,"Error: SLL Encapsulation Function given bad data!\n");
325                 return 0;
326         }
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");
329                 return 0;
330         }
331
332         /*Copy SLL header over*/
333         memcpy(new->data, old->data, sizeof(struct sll_header));
334
335         /*Cast Pointer*/
336         slh=(struct sll_header*)(new->data);
337
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);
343         nnew.h=new->h;
344         nold.h=old->h;
345         nnew.print_id=NULL;
346         nnew.dest_id=NULL;
347         nnew.src_id=NULL;
348         nnew.id_len=0;
349         nold.print_id=NULL;
350         nold.dest_id=NULL;
351         nold.src_id=NULL;
352         nold.id_len=0;
353
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");
357                 return 0;
358         }
359
360         /*Select Next Protocol*/
361         switch(ntohs(slh->sll_protocol)){
362                 case ETHERTYPE_IP:
363                                 if(!ipv4_encap(&nnew, &nold)){
364                                                 return 0;
365                                 }
366                                 break;
367                 case ETHERTYPE_IPV6:
368                                 if(!ipv6_encap(&nnew, &nold)){
369                                                 return 0;
370                                 }
371                                 break;
372                 default:
373                                 dbgprintf(1, "Unknown Next Protocol at SLL\n");
374                                 return 0;
375                                 break;
376         }
377
378         /*Adjust length*/
379         new->length=nnew.length + sizeof(struct sll_header);
380 return 1;
381 }
382
383
384 char *print_ipv6(char* buf, int len, u_char* id, int id_len)
385 {
386         struct sockaddr_in6 sa;
387
388         if(buf==NULL){
389                 return NULL;
390         }
391
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){
396                 return NULL;
397         }
398         return buf;
399 }
400
401 char *print_ipv4(char* buf, int len, u_char* id, int id_len)
402 {
403         struct sockaddr_in sa;
404
405         if(buf==NULL){
406                 return NULL;
407         }
408
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){
413                 return NULL;
414         }
415         return buf;
416 }