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