]> sjero.net Git - dccp2tcp/blob - encap.c
Minor Makefile change for greater compatibility
[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 <pcap/vlan.h>
28 #include <netinet/ip6.h>
29 #include <netdb.h>
30
31 /*Encapsulation start point and link layer selector*/
32 int do_encap(int link, struct packet *new, const struct const_packet *old)
33 {
34         switch(link){
35                 case DLT_EN10MB:
36                                 /*Ethernet*/
37                                 if(!ethernet_encap(new, old)){
38                                                 return 0;
39                                 }
40                                 break;
41                 case DLT_RAW:
42                                 /*Raw. Just IP*/
43                                 if(!ipv4_encap(new, old)){
44                                                 return 0;
45                                 }
46                                 break;
47                 case DLT_LINUX_SLL:
48                                 /*Linux Cooked Capture*/
49                                 if(!linux_cooked_encap(new, old)){
50                                         return 0;
51                                 }
52                                 break;
53                 default:
54                                 dbgprintf(0, "Unknown Link Layer\n");
55                                 return 0;
56         }
57
58         /*Adjust libpcap header*/
59         if(new->h->caplen >= new->h->len || new->h->caplen >= new->length){
60                 new->h->caplen=new->length;
61         }
62         new->h->len=new->length;
63
64 return 1;
65 }
66
67 /*Standard Ethernet Encapsulation*/
68 int ethernet_encap(struct packet *new, const struct const_packet *old)
69 {
70                 struct ether_header     *ethh;
71                 struct const_packet nold;
72                 struct packet           nnew;
73
74                 /*Safety checks*/
75                 if(!new || !old || !new->data || !old->data || !new->h || !old->h){
76                         dbgprintf(0,"Error: Ethernet Encapsulation Function given bad data!\n");
77                         return 0;
78                 }
79                 if(old->length < sizeof(struct ether_header) || new->length < sizeof(struct ether_header)){
80                         dbgprintf(0, "Error: Ethernet Encapsulation Function given packet of wrong size!\n");
81                         return 0;
82                 }
83
84                 /*Copy Ethernet header over*/
85                 memcpy(new->data, old->data, sizeof(struct ether_header));
86
87                 /*Cast Pointer*/
88                 ethh=(struct ether_header*)(new->data);
89
90                 /*Adjust pointers and lengths*/
91                 nold.data= old->data+ sizeof(struct ether_header);
92                 nnew.data= new->data + sizeof(struct ether_header);
93                 nold.length= old->length - sizeof(struct ether_header);
94                 nnew.length= new->length - sizeof(struct ether_header);
95                 nnew.h=new->h;
96                 nold.h=old->h;
97                 nnew.print_id=NULL;
98                 nnew.dest_id=NULL;
99                 nnew.src_id=NULL;
100                 nnew.id_len=0;
101                 nold.print_id=NULL;
102                 nold.dest_id=NULL;
103                 nold.src_id=NULL;
104                 nold.id_len=0;
105
106                 /*Select Next Protocol*/
107                 switch(ntohs(ethh->ether_type)){
108                         case ETHERTYPE_IP:
109                                         if(!ipv4_encap(&nnew, &nold)){
110                                                         return 0;
111                                         }
112                                         break;
113                         case ETHERTYPE_IPV6:
114                                         if(!ipv6_encap(&nnew, &nold)){
115                                                         return 0;
116                                         }
117                                         break;
118                         case ETHERTYPE_VLAN:
119                                         if(!ethernet_vlan_encap(&nnew, &nold)){
120                                                         return 0;
121                                         }
122                                         break;
123                         default:
124                                         dbgprintf(1, "Unknown Next Protocol at Ethernet\n");
125                                         return 0;
126                                         break;
127                 }
128
129                 /*Adjust length*/
130                 new->length=nnew.length + sizeof(struct ether_header);
131 return 1;
132 }
133
134 /*Ethernet 802.1Q VLAN Encapsulation*/
135 int ethernet_vlan_encap(struct packet *new, const struct const_packet *old)
136 {
137                 struct vlan_tag         *tag;
138                 struct const_packet nold;
139                 struct packet           nnew;
140
141                 /*Safety checks*/
142                 if(!new || !old || !new->data || !old->data || !new->h || !old->h){
143                         dbgprintf(0,"Error: Ethernet VLAN Encapsulation Function given bad data!\n");
144                         return 0;
145                 }
146                 if(old->length < sizeof(struct vlan_tag) || new->length < sizeof(struct vlan_tag)){
147                         dbgprintf(0, "Error: Ethernet VLAN Encapsulation Function given packet of wrong size!\n");
148                         return 0;
149                 }
150
151                 /*Copy VLAN tag over*/
152                 memcpy(new->data, old->data, sizeof(struct vlan_tag));
153
154                 /*Cast Pointer*/
155                 tag=(struct vlan_tag*)(new->data);
156
157                 /*Adjust pointers and lengths*/
158                 nold.data= old->data+ sizeof(struct vlan_tag);
159                 nnew.data= new->data + sizeof(struct vlan_tag);
160                 nold.length= old->length - sizeof(struct vlan_tag);
161                 nnew.length= new->length - sizeof(struct vlan_tag);
162                 nnew.h=new->h;
163                 nold.h=old->h;
164                 nnew.print_id=NULL;
165                 nnew.dest_id=NULL;
166                 nnew.src_id=NULL;
167                 nnew.id_len=0;
168                 nold.print_id=NULL;
169                 nold.dest_id=NULL;
170                 nold.src_id=NULL;
171                 nold.id_len=0;
172
173                 /*Select Next Protocol*/
174                 switch(ntohs(tag->vlan_tci)){
175                         case ETHERTYPE_IP:
176                                         if(!ipv4_encap(&nnew, &nold)){
177                                                         return 0;
178                                         }
179                                         break;
180                         case ETHERTYPE_IPV6:
181                                         if(!ipv6_encap(&nnew, &nold)){
182                                                         return 0;
183                                         }
184                                         break;
185                         case ETHERTYPE_VLAN:
186                                         if(!ethernet_vlan_encap(&nnew, &nold)){
187                                                         return 0;
188                                         }
189                                         break;
190                         default:
191                                         dbgprintf(1, "Unknown Next Protocol at Ethernet VLAN tag\n");
192                                         return 0;
193                                         break;
194                 }
195
196                 /*Adjust length*/
197                 new->length=nnew.length + sizeof(struct vlan_tag);
198 return 1;
199 }
200
201 /*IPv6 Encapsulation*/
202 int ipv6_encap(struct packet *new, const struct const_packet *old)
203 {
204                 struct ip6_hdr          *iph;
205                 struct packet           nnew;
206                 struct const_packet     nold;
207
208                 /*Safety checks*/
209                 if(!new || !old || !new->data || !old->data || !new->h || !old->h){
210                         dbgprintf(0,"Error: IPv6 Encapsulation Function given bad data!\n");
211                         return 0;
212                 }
213                 if(old->length < sizeof(struct ip6_hdr) || new->length < sizeof(struct ip6_hdr)){
214                         dbgprintf(0, "Error: IPv6 Encapsulation Function given packet of wrong size!\n");
215                         return 0;
216                 }
217
218                 /*Copy IPv6 header over*/
219                 memcpy(new->data, old->data, sizeof(struct ip6_hdr));
220
221                 /*Cast Pointer*/
222                 iph=(struct ip6_hdr*)(new->data);
223
224                 /*Adjust pointers and lengths*/
225                 nold.data= old->data + sizeof(struct ip6_hdr);
226                 nnew.data= new->data +sizeof(struct ip6_hdr);
227                 nold.length= old->length - sizeof(struct ip6_hdr);
228                 nnew.length= new->length - sizeof(struct ip6_hdr);
229                 nnew.h=new->h;
230                 nold.h=old->h;
231                 nnew.print_id=print_ipv6;
232                 nold.print_id=print_ipv6;
233                 nnew.id_len=16;
234                 nold.id_len=16;
235
236                 /*Confirm that this is IPv6*/
237                 if((ntohl(iph->ip6_ctlun.ip6_un1.ip6_un1_flow) & (0xF0000000)) == (60000000)){
238                         dbgprintf(1, "Note: Packet is not IPv6\n");
239                         return 0;
240                 }
241
242                 /*Select Next Protocol*/
243                 switch(iph->ip6_ctlun.ip6_un1.ip6_un1_nxt){
244                         case 33:
245                                         /*DCCP*/
246                                         nnew.src_id=malloc(nnew.id_len);
247                                         nnew.dest_id=malloc(nnew.id_len);
248                                         nold.src_id=malloc(nold.id_len);
249                                         nold.dest_id=malloc(nold.id_len);
250                                         if(nnew.src_id==NULL||nnew.dest_id==NULL ||
251                                                 nold.src_id==NULL||nold.dest_id==NULL){
252                                                 dbgprintf(0,"Error: Couldn't allocate Memory\n");
253                                                 exit(1);
254                                         }
255                                         memcpy(nnew.src_id,&iph->ip6_src,nnew.id_len);
256                                         memcpy(nnew.dest_id,&iph->ip6_dst,nnew.id_len);
257                                         memcpy(nold.src_id,&iph->ip6_src,nold.id_len);
258                                         memcpy(nold.dest_id,&iph->ip6_dst,nold.id_len);
259                                         if(!convert_packet(&nnew, &nold)){
260                                                 return 0;
261                                         }
262                                         break;
263                         default:
264                                         dbgprintf(1, "Unknown Next Protocol at IPv6\n");
265                                         return 0;
266                                         break;
267                 }
268
269                 /*set ip to indicate that TCP is next protocol*/
270                 iph->ip6_ctlun.ip6_un1.ip6_un1_nxt=6;
271
272                 /*Determine if computed length is reasonable*/
273                 if(nnew.length > 0xFFFF){
274                                 dbgprintf(1, "Error: Given TCP data length is too large for an IPv6 packet!\n");
275                                 return 0;
276                 }
277
278                 /*Adjust IPv6 header to account for packet's total length*/
279                 iph->ip6_ctlun.ip6_un1.ip6_un1_plen=htons(nnew.length);
280
281                 /*Adjust length*/
282                 new->length=nnew.length + sizeof(struct ip6_hdr);
283
284                 /*Cleanup*/
285                 free(nnew.dest_id);
286                 free(nnew.src_id);
287                 free(nold.dest_id);
288                 free(nold.src_id);
289 return 1;
290 }
291
292 /*IPv4 Encapsulation*/
293 int ipv4_encap(struct packet *new, const struct const_packet *old)
294 {
295                 struct iphdr            *iph;
296                 struct packet           nnew;
297                 struct const_packet     nold;
298
299                 /*Safety checks*/
300                 if(!new || !old || !new->data || !old->data || !new->h || !old->h){
301                         dbgprintf(0,"Error: IPv4 Encapsulation Function given bad data!\n");
302                         return 0;
303                 }
304                 if(old->length < sizeof(struct iphdr) || new->length < sizeof(struct iphdr)){
305                         dbgprintf(0, "Error: IPv4 Encapsulation Function given packet of wrong size!\n");
306                         return 0;
307                 }
308
309                 /*Copy IPv4 header over*/
310                 memcpy(new->data, old->data, sizeof(struct iphdr));
311
312                 /*Cast Pointer*/
313                 iph=(struct iphdr*)(new->data);
314
315                 /*Adjust pointers and lengths*/
316                 nold.data= old->data +iph->ihl*4;
317                 nnew.data= new->data +iph->ihl*4;
318                 nold.length= old->length -iph->ihl*4;
319                 nnew.length= new->length -iph->ihl*4;
320                 nnew.h=new->h;
321                 nold.h=old->h;
322                 nnew.print_id=print_ipv4;
323                 nold.print_id=print_ipv4;
324                 nnew.id_len=4;
325                 nold.id_len=4;
326
327                 /*Confirm that this is IPv4*/
328                 if(iph->version!=4){
329                         dbgprintf(1, "Note: Packet is not IPv4\n");
330                         return 0;
331                 }
332
333                 /*Select Next Protocol*/
334                 switch(iph->protocol){
335                         case 33:
336                                         /*DCCP*/
337                                         nnew.src_id=malloc(nnew.id_len);
338                                         nnew.dest_id=malloc(nnew.id_len);
339                                         nold.src_id=malloc(nold.id_len);
340                                         nold.dest_id=malloc(nold.id_len);
341                                         if(nnew.src_id==NULL||nnew.dest_id==NULL||
342                                                         nold.src_id==NULL||nold.dest_id==NULL){
343                                                 dbgprintf(0,"Error: Couldn't allocate Memory\n");
344                                                 exit(1);
345                                         }
346                                         memcpy(nnew.src_id,&iph->saddr,nnew.id_len);
347                                         memcpy(nnew.dest_id,&iph->daddr,nnew.id_len);
348                                         memcpy(nold.src_id,&iph->saddr,nold.id_len);
349                                         memcpy(nold.dest_id,&iph->daddr,nold.id_len);
350                                         if(!convert_packet(&nnew, &nold)){
351                                                 return 0;
352                                         }
353                                         break;
354                         default:
355                                         dbgprintf(1, "Unknown Next Protocol at IPv4\n");
356                                         return 0;
357                                         break;
358                 }
359
360                 /*set ip to indicate that TCP is next protocol*/
361                 iph->protocol=6;
362                 iph->check=htonl(0);
363
364                 /*Adjust length*/
365                 new->length=nnew.length + iph->ihl*4;
366
367                 /*Determine if computed length is reasonable*/
368                 if(nnew.length > 0xFFFF){
369                                 dbgprintf(1, "Error: Given TCP header+data length is too large for an IPv4 packet!\n");
370                                 return 0;
371                 }
372
373                 /*Adjust IPv4 header to account for packet's total length*/
374                 iph->tot_len=htons(new->length);
375
376                 /*Compute IPv4 Checksum*/
377                 iph->check=0;
378                 iph->check=ipv4_chksum(new->data,iph->ihl*4);
379
380                 /*Cleanup*/
381                 free(nnew.src_id);
382                 free(nnew.dest_id);
383                 free(nold.src_id);
384                 free(nold.dest_id);
385 return 1;
386 }
387
388 int linux_cooked_encap(struct packet *new, const struct const_packet *old)
389 {
390         struct sll_header               *slh;
391         struct packet                   nnew;
392         struct const_packet             nold;
393
394
395         /*Safety checks*/
396         if(!new|| !old || !new->data || !old->data || !new->h || !old->h){
397                 dbgprintf(0,"Error: SLL Encapsulation Function given bad data!\n");
398                 return 0;
399         }
400         if(old->length < sizeof(struct sll_header) || new->length < sizeof(struct sll_header)){
401                 dbgprintf(0, "Error: SLL Encapsulation Function given packet of wrong size!\n");
402                 return 0;
403         }
404
405         /*Copy SLL header over*/
406         memcpy(new->data, old->data, sizeof(struct sll_header));
407
408         /*Cast Pointer*/
409         slh=(struct sll_header*)(new->data);
410
411         /*Adjust pointers and lengths*/
412         nold.data= old->data + sizeof(struct sll_header);
413         nnew.data= new->data + sizeof(struct sll_header);
414         nold.length= old->length - sizeof(struct sll_header);
415         nnew.length= new->length- sizeof(struct sll_header);
416         nnew.h=new->h;
417         nold.h=old->h;
418         nnew.print_id=NULL;
419         nnew.dest_id=NULL;
420         nnew.src_id=NULL;
421         nnew.id_len=0;
422         nold.print_id=NULL;
423         nold.dest_id=NULL;
424         nold.src_id=NULL;
425         nold.id_len=0;
426
427         /*Confirm that this is SLL*/
428         if(ntohs(slh->sll_pkttype) > 4){
429                 dbgprintf(1, "Note: Packet is not SLL (Linux Cooked Capture)\n");
430                 return 0;
431         }
432
433         /*Select Next Protocol*/
434         switch(ntohs(slh->sll_protocol)){
435                 case ETHERTYPE_IP:
436                                 if(!ipv4_encap(&nnew, &nold)){
437                                                 return 0;
438                                 }
439                                 break;
440                 case ETHERTYPE_IPV6:
441                                 if(!ipv6_encap(&nnew, &nold)){
442                                                 return 0;
443                                 }
444                                 break;
445                 default:
446                                 dbgprintf(1, "Unknown Next Protocol at SLL\n");
447                                 return 0;
448                                 break;
449         }
450
451         /*Adjust length*/
452         new->length=nnew.length + sizeof(struct sll_header);
453 return 1;
454 }
455
456
457 char *print_ipv6(char* buf, int len, u_char* id, int id_len)
458 {
459         struct sockaddr_in6 sa;
460
461         if(buf==NULL){
462                 return NULL;
463         }
464
465         memcpy(&sa.sin6_addr, id, id_len);
466         sa.sin6_family=AF_INET6;
467         if(getnameinfo((struct sockaddr*)&sa, sizeof(struct sockaddr_in6),
468                                                                                         buf, len, NULL,0,NI_NUMERICHOST)<0){
469                 return NULL;
470         }
471         return buf;
472 }
473
474 char *print_ipv4(char* buf, int len, u_char* id, int id_len)
475 {
476         struct sockaddr_in sa;
477
478         if(buf==NULL){
479                 return NULL;
480         }
481
482         memcpy(&sa.sin_addr, id, id_len);
483         sa.sin_family=AF_INET;
484         if(getnameinfo((struct sockaddr*)&sa, sizeof(struct sockaddr_in),
485                                                                                         buf, len, NULL,0,NI_NUMERICHOST)<0){
486                 return NULL;
487         }
488         return buf;
489 }