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