]> sjero.net Git - dccp2tcp/blob - encap.c
Multiple Connection Support
[dccp2tcp] / encap.c
1 /******************************************************************************
2 Author: Samuel Jero
3
4 Date: 7/2011
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
13 /*Encapsulation start point and link layer selector*/
14 int do_encap(int link, struct packet *new, const struct const_packet *old)
15 {
16         switch(link){
17                 case DLT_EN10MB:
18                                 /*Ethernet*/
19                                 if(!ethernet_encap(new, old)){
20                                                 return 0;
21                                 }
22                                 break;
23                 case DLT_RAW:
24                                 /*Raw. Just IP*/
25                                 if(!ipv4_encap(new, old)){
26                                                 return 0;
27                                 }
28                                 break;
29                 case DLT_LINUX_SLL:
30                                 /*Linux Cooked Capture*/
31                                 if(!linux_cooked_encap(new, old)){
32                                         return 0;
33                                 }
34                                 break;
35                 default:
36                                 dbgprintf(0, "Unknown Link Layer\n");
37                                 return 0;
38         }
39
40         /*Adjust libpcap header*/
41         if(new->h->caplen >= new->h->len || new->h->caplen >= new->length){
42                 new->h->caplen=new->length;
43         }
44         new->h->len=new->length;
45
46 return 1;
47 }
48
49 /*Standard Ethernet Encapsulation*/
50 int ethernet_encap(struct packet *new, const struct const_packet *old)
51 {
52                 struct ether_header     *ethh;
53                 struct const_packet nold;
54                 struct packet           nnew;
55
56                 /*Safety checks*/
57                 if(!new || !old || !new->data || !old->data || !new->h || !old->h){
58                         dbgprintf(0,"Error: Ethernet Encapsulation Function given bad data!\n");
59                         return 0;
60                 }
61                 if(old->length < sizeof(struct ether_header) || new->length < sizeof(struct ether_header)){
62                         dbgprintf(0, "Error: Ethernet Encapsulation Function given packet of wrong size!\n");
63                         return 0;
64                 }
65
66                 /*Copy Ethernet header over*/
67                 memcpy(new->data, old->data, sizeof(struct ether_header));
68
69                 /*Cast Pointer*/
70                 ethh=(struct ether_header*)(new->data);
71
72                 /*Adjust pointers and lengths*/
73                 nold.data= old->data+ sizeof(struct ether_header);
74                 nnew.data= new->data + sizeof(struct ether_header);
75                 nold.length= old->length - sizeof(struct ether_header);
76                 nnew.length= new->length - sizeof(struct ether_header);
77
78                 /*Select Next Protocol*/
79                 switch(ntohs(ethh->ether_type)){
80                         case ETHERTYPE_IP:
81                                         if(!ipv4_encap(&nnew, &nold)){
82                                                         return 0;
83                                         }
84                                         break;
85                         default:
86                                         dbgprintf(1, "Unknown Next Protocol at Ethernet\n");
87                                         return 0;
88                                         break;
89                 }
90
91                 /*Adjust length*/
92                 new->length=nnew.length + sizeof(struct ether_header);
93 return 1;
94 }
95
96 /*IPv4 Encapsulation*/
97 int ipv4_encap(struct packet *new, const struct const_packet *old)
98 {
99                 struct iphdr            *iph;
100                 struct packet           nnew;
101                 struct const_packet     nold;
102
103                 /*Safety checks*/
104                 if(!new || !old || !new->data || !old->data || !new->h || !old->h){
105                         dbgprintf(0,"Error: IPv4 Encapsulation Function given bad data!\n");
106                         return 0;
107                 }
108                 if(old->length < sizeof(struct iphdr) || new->length < sizeof(struct iphdr)){
109                         dbgprintf(0, "Error: IPv4 Encapsulation Function given packet of wrong size!\n");
110                         return 0;
111                 }
112
113                 /*Copy IPv4 header over*/
114                 memcpy(new->data, old->data, sizeof(struct iphdr));
115
116                 /*Cast Pointer*/
117                 iph=(struct iphdr*)(new->data);
118
119                 /*Adjust pointers and lengths*/
120                 nold.data= old->data +iph->ihl*4;
121                 nnew.data= new->data +iph->ihl*4;
122                 nold.length= old->length -iph->ihl*4;
123                 nnew.length= new->length -iph->ihl*4;
124
125                 /*Confirm that this is IPv4*/
126                 if(iph->version!=4){
127                         dbgprintf(1, "Note: Packet is not IPv4\n");
128                         return 0;
129                 }
130
131                 /*Select Next Protocol*/
132                 switch(iph->protocol){
133                         case 0x21:
134                                         /*DCCP*/
135                                         nnew.src_id=iph->saddr;
136                                         nnew.dest_id=iph->daddr;
137                                         if(!convert_packet(&nnew, &nold)){
138                                                 return 0;
139                                         }
140                                         break;
141                         default:
142                                         dbgprintf(1, "Unknown Next Protocol at IPv4\n");
143                                         return 0;
144                                         break;
145                 }
146
147                 /*set ip to indicate that TCP is next protocol*/
148                 iph->protocol=6;
149                 iph->check=htonl(0);
150
151                 /*Adjust length*/
152                 new->length=nnew.length + iph->ihl*4;
153
154                 /*Determine if computed length is reasonable*/
155                 if(nnew.length > 0xFFFF){
156                                 dbgprintf(1, "Error: Given TCP header+data length is too large for an IPv4 packet!\n");
157                                 return 0;
158                 }
159
160                 /*Adjust IPv4 header to account for packet's total length*/
161                 iph->tot_len=htons(nnew.length);
162 return 1;
163 }
164
165 int linux_cooked_encap(struct packet *new, const struct const_packet *old)
166 {
167         struct sll_header               *slh;
168         struct packet                   nnew;
169         struct const_packet             nold;
170
171
172         /*Safety checks*/
173         if(!new|| !old || !new->data || !old->data || !new->h || !old->h){
174                 dbgprintf(0,"Error: SLL Encapsulation Function given bad data!\n");
175                 return 0;
176         }
177         if(old->length < sizeof(struct sll_header) || new->length < sizeof(struct sll_header)){
178                 dbgprintf(0, "Error: SLL Encapsulation Function given packet of wrong size!\n");
179                 return 0;
180         }
181
182         /*Copy SLL header over*/
183         memcpy(new->data, old->data, sizeof(struct sll_header));
184
185         /*Cast Pointer*/
186         slh=(struct sll_header*)(new->data);
187
188         /*Adjust pointers and lengths*/
189         nold.data= old->data + sizeof(struct sll_header);
190         nnew.data= new->data + sizeof(struct sll_header);
191         nold.length= old->length - sizeof(struct sll_header);
192         nnew.length= new->length- sizeof(struct sll_header);
193
194         /*Confirm that this is SLL*/
195         if(ntohs(slh->sll_pkttype) > 4){
196                 dbgprintf(1, "Note: Packet is not SLL (Linux Cooked Capture)\n");
197                 return 0;
198         }
199
200         /*Select Next Protocol*/
201         switch(ntohs(slh->sll_protocol)){
202                 case ETHERTYPE_IP:
203                                 if(!ipv4_encap(&nnew, &nold)){
204                                                 return 0;
205                                 }
206                                 break;
207                 default:
208                                 dbgprintf(1, "Unknown Next Protocol at SLL\n");
209                                 return 0;
210                                 break;
211         }
212
213         /*Adjust length*/
214         new->length=nnew.length + sizeof(struct sll_header);
215 return 1;
216 }