]> sjero.net Git - dccp2tcp/blob - encap.c
Cleanup types throughout code
[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
29 /*Encapsulation start point and link layer selector*/
30 int do_encap(int link, struct packet *new, const struct const_packet *old)
31 {
32         switch(link){
33                 case DLT_EN10MB:
34                                 /*Ethernet*/
35                                 if(!ethernet_encap(new, old)){
36                                                 return 0;
37                                 }
38                                 break;
39                 case DLT_RAW:
40                                 /*Raw. Just IP*/
41                                 if(!ipv4_encap(new, old)){
42                                                 return 0;
43                                 }
44                                 break;
45                 case DLT_LINUX_SLL:
46                                 /*Linux Cooked Capture*/
47                                 if(!linux_cooked_encap(new, old)){
48                                         return 0;
49                                 }
50                                 break;
51                 default:
52                                 dbgprintf(0, "Unknown Link Layer\n");
53                                 return 0;
54         }
55
56         /*Adjust libpcap header*/
57         if(new->h->caplen >= new->h->len || new->h->caplen >= new->length){
58                 new->h->caplen=new->length;
59         }
60         new->h->len=new->length;
61
62 return 1;
63 }
64
65 /*Standard Ethernet Encapsulation*/
66 int ethernet_encap(struct packet *new, const struct const_packet *old)
67 {
68                 struct ether_header     *ethh;
69                 struct const_packet nold;
70                 struct packet           nnew;
71
72                 /*Safety checks*/
73                 if(!new || !old || !new->data || !old->data || !new->h || !old->h){
74                         dbgprintf(0,"Error: Ethernet Encapsulation Function given bad data!\n");
75                         return 0;
76                 }
77                 if(old->length < sizeof(struct ether_header) || new->length < sizeof(struct ether_header)){
78                         dbgprintf(0, "Error: Ethernet Encapsulation Function given packet of wrong size!\n");
79                         return 0;
80                 }
81
82                 /*Copy Ethernet header over*/
83                 memcpy(new->data, old->data, sizeof(struct ether_header));
84
85                 /*Cast Pointer*/
86                 ethh=(struct ether_header*)(new->data);
87
88                 /*Adjust pointers and lengths*/
89                 nold.data= old->data+ sizeof(struct ether_header);
90                 nnew.data= new->data + sizeof(struct ether_header);
91                 nold.length= old->length - sizeof(struct ether_header);
92                 nnew.length= new->length - sizeof(struct ether_header);
93                 nnew.h=new->h;
94                 nold.h=old->h;
95
96                 /*Select Next Protocol*/
97                 switch(ntohs(ethh->ether_type)){
98                         case ETHERTYPE_IP:
99                                         if(!ipv4_encap(&nnew, &nold)){
100                                                         return 0;
101                                         }
102                                         break;
103                         case ETHERTYPE_IPV6:
104                                         if(!ipv6_encap(&nnew, &nold)){
105                                                         return 0;
106                                         }
107                                         break;
108                         default:
109                                         dbgprintf(1, "Unknown Next Protocol at Ethernet\n");
110                                         return 0;
111                                         break;
112                 }
113
114                 /*Adjust length*/
115                 new->length=nnew.length + sizeof(struct ether_header);
116 return 1;
117 }
118
119 /*IPv6 Encapsulation*/
120 int ipv6_encap(struct packet *new, const struct const_packet *old)
121 {
122                 struct ip6_hdr          *iph;
123                 struct packet           nnew;
124                 struct const_packet     nold;
125
126                 /*Safety checks*/
127                 if(!new || !old || !new->data || !old->data || !new->h || !old->h){
128                         dbgprintf(0,"Error: IPv6 Encapsulation Function given bad data!\n");
129                         return 0;
130                 }
131                 if(old->length < sizeof(struct ip6_hdr) || new->length < sizeof(struct ip6_hdr)){
132                         dbgprintf(0, "Error: IPv6 Encapsulation Function given packet of wrong size!\n");
133                         return 0;
134                 }
135
136                 /*Copy IPv6 header over*/
137                 memcpy(new->data, old->data, sizeof(struct ip6_hdr));
138
139                 /*Cast Pointer*/
140                 iph=(struct ip6_hdr*)(new->data);
141
142                 /*Adjust pointers and lengths*/
143                 nold.data= old->data + sizeof(struct ip6_hdr);
144                 nnew.data= new->data +sizeof(struct ip6_hdr);
145                 nold.length= old->length - sizeof(struct ip6_hdr);
146                 nnew.length= new->length - sizeof(struct ip6_hdr);
147                 nnew.h=new->h;
148                 nold.h=old->h;
149
150                 /*Confirm that this is IPv6*/
151                 if((ntohl(iph->ip6_ctlun.ip6_un1.ip6_un1_flow) & (0xF0000000)) == (60000000)){
152                         dbgprintf(1, "Note: Packet is not IPv6\n");
153                         return 0;
154                 }
155
156                 /*Select Next Protocol*/
157                 switch(iph->ip6_ctlun.ip6_un1.ip6_un1_nxt){
158                         case 33:
159                                         /*DCCP*/
160                                         nnew.id_len=16;
161                                         nnew.src_id=malloc(nnew.id_len);
162                                         nnew.dest_id=malloc(nnew.id_len);
163                                         if(nnew.src_id==NULL||nnew.dest_id==NULL){
164                                                 dbgprintf(0,"Error: Couldn't allocate Memory\n");
165                                                 exit(1);
166                                         }
167                                         memcpy(nnew.src_id,&iph->ip6_src,nnew.id_len);
168                                         memcpy(nnew.dest_id,&iph->ip6_dst,nnew.id_len);
169                                         if(!convert_packet(&nnew, &nold)){
170                                                 return 0;
171                                         }
172                                         break;
173                         default:
174                                         dbgprintf(1, "Unknown Next Protocol at IPv6\n");
175                                         return 0;
176                                         break;
177                 }
178
179                 /*set ip to indicate that TCP is next protocol*/
180                 iph->ip6_ctlun.ip6_un1.ip6_un1_nxt=6;
181
182                 /*Determine if computed length is reasonable*/
183                 if(nnew.length > 0xFFFF){
184                                 dbgprintf(1, "Error: Given TCP data length is too large for an IPv6 packet!\n");
185                                 return 0;
186                 }
187
188                 /*Adjust IPv6 header to account for packet's total length*/
189                 iph->ip6_ctlun.ip6_un1.ip6_un1_plen=htons(nnew.length);
190
191                 /*Adjust length*/
192                 new->length=nnew.length + sizeof(struct ip6_hdr);
193
194                 /*Cleanup*/
195                 free(nnew.dest_id);
196                 free(nnew.src_id);
197 return 1;
198 }
199
200 /*IPv4 Encapsulation*/
201 int ipv4_encap(struct packet *new, const struct const_packet *old)
202 {
203                 struct iphdr            *iph;
204                 struct packet           nnew;
205                 struct const_packet     nold;
206
207                 /*Safety checks*/
208                 if(!new || !old || !new->data || !old->data || !new->h || !old->h){
209                         dbgprintf(0,"Error: IPv4 Encapsulation Function given bad data!\n");
210                         return 0;
211                 }
212                 if(old->length < sizeof(struct iphdr) || new->length < sizeof(struct iphdr)){
213                         dbgprintf(0, "Error: IPv4 Encapsulation Function given packet of wrong size!\n");
214                         return 0;
215                 }
216
217                 /*Copy IPv4 header over*/
218                 memcpy(new->data, old->data, sizeof(struct iphdr));
219
220                 /*Cast Pointer*/
221                 iph=(struct iphdr*)(new->data);
222
223                 /*Adjust pointers and lengths*/
224                 nold.data= old->data +iph->ihl*4;
225                 nnew.data= new->data +iph->ihl*4;
226                 nold.length= old->length -iph->ihl*4;
227                 nnew.length= new->length -iph->ihl*4;
228                 nnew.h=new->h;
229                 nold.h=old->h;
230
231                 /*Confirm that this is IPv4*/
232                 if(iph->version!=4){
233                         dbgprintf(1, "Note: Packet is not IPv4\n");
234                         return 0;
235                 }
236
237                 /*Select Next Protocol*/
238                 switch(iph->protocol){
239                         case 33:
240                                         /*DCCP*/
241                                         nnew.id_len=4;
242                                         nnew.src_id=malloc(nnew.id_len);
243                                         nnew.dest_id=malloc(nnew.id_len);
244                                         if(nnew.src_id==NULL||nnew.dest_id==NULL){
245                                                 dbgprintf(0,"Error: Couldn't allocate Memory\n");
246                                                 exit(1);
247                                         }
248                                         memcpy(nnew.src_id,&iph->saddr,nnew.id_len);
249                                         memcpy(nnew.dest_id,&iph->daddr,nnew.id_len);
250                                         if(!convert_packet(&nnew, &nold)){
251                                                 return 0;
252                                         }
253                                         break;
254                         default:
255                                         dbgprintf(1, "Unknown Next Protocol at IPv4\n");
256                                         return 0;
257                                         break;
258                 }
259
260                 /*set ip to indicate that TCP is next protocol*/
261                 iph->protocol=6;
262                 iph->check=htonl(0);
263
264                 /*Adjust length*/
265                 new->length=nnew.length + iph->ihl*4;
266
267                 /*Determine if computed length is reasonable*/
268                 if(nnew.length > 0xFFFF){
269                                 dbgprintf(1, "Error: Given TCP header+data length is too large for an IPv4 packet!\n");
270                                 return 0;
271                 }
272
273                 /*Adjust IPv4 header to account for packet's total length*/
274                 iph->tot_len=htons(new->length);
275
276                 /*Compute IPv4 Checksum*/
277                 iph->check=0;
278                 iph->check=ipv4_chksum(new->data,iph->ihl*4);
279
280                 /*Cleanup*/
281                 free(nnew.src_id);
282                 free(nnew.dest_id);
283 return 1;
284 }
285
286 int linux_cooked_encap(struct packet *new, const struct const_packet *old)
287 {
288         struct sll_header               *slh;
289         struct packet                   nnew;
290         struct const_packet             nold;
291
292
293         /*Safety checks*/
294         if(!new|| !old || !new->data || !old->data || !new->h || !old->h){
295                 dbgprintf(0,"Error: SLL Encapsulation Function given bad data!\n");
296                 return 0;
297         }
298         if(old->length < sizeof(struct sll_header) || new->length < sizeof(struct sll_header)){
299                 dbgprintf(0, "Error: SLL Encapsulation Function given packet of wrong size!\n");
300                 return 0;
301         }
302
303         /*Copy SLL header over*/
304         memcpy(new->data, old->data, sizeof(struct sll_header));
305
306         /*Cast Pointer*/
307         slh=(struct sll_header*)(new->data);
308
309         /*Adjust pointers and lengths*/
310         nold.data= old->data + sizeof(struct sll_header);
311         nnew.data= new->data + sizeof(struct sll_header);
312         nold.length= old->length - sizeof(struct sll_header);
313         nnew.length= new->length- sizeof(struct sll_header);
314         nnew.h=new->h;
315         nold.h=old->h;
316
317         /*Confirm that this is SLL*/
318         if(ntohs(slh->sll_pkttype) > 4){
319                 dbgprintf(1, "Note: Packet is not SLL (Linux Cooked Capture)\n");
320                 return 0;
321         }
322
323         /*Select Next Protocol*/
324         switch(ntohs(slh->sll_protocol)){
325                 case ETHERTYPE_IP:
326                                 if(!ipv4_encap(&nnew, &nold)){
327                                                 return 0;
328                                 }
329                                 break;
330                 case ETHERTYPE_IPV6:
331                                 if(!ipv6_encap(&nnew, &nold)){
332                                                 return 0;
333                                 }
334                                 break;
335                 default:
336                                 dbgprintf(1, "Unknown Next Protocol at SLL\n");
337                                 return 0;
338                                 break;
339         }
340
341         /*Adjust length*/
342         new->length=nnew.length + sizeof(struct sll_header);
343 return 1;
344 }