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