"Fossies" - the Fresh Open Source Software Archive 
Member "ettercap-0.8.3.1/src/protocols/ec_ip6.c" (1 Aug 2020, 8855 Bytes) of package /linux/privat/ettercap-0.8.3.1.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "ec_ip6.c" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
0.8.3_vs_0.8.3.1.
1 /*
2 ettercap -- IPv6 decoder module
3
4 Copyright (C) ALoR & NaGA
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20 */
21
22 #include <ec.h>
23 #include <ec_decode.h>
24 #include <ec_inject.h>
25 #include <ec_inet.h>
26 #include <ec_session.h>
27 //#include <ec_fingerprint.h>
28
29 #define IP6_HDR_LEN 40
30
31 /* globals */
32
33 struct ip6_header {
34 #ifndef WORDS_BIGENDIAN
35 u_int8 version:4;
36 u_int8 priority:4;
37 #else
38 u_int8 priority:4;
39 u_int8 version:4;
40 #endif
41 u_int8 flow_lbl[3];
42 u_int16 payload_len;
43 u_int8 next_hdr;
44 u_int8 hop_limit;
45
46 u_int8 saddr[IP6_ADDR_LEN];
47 u_int8 daddr[IP6_ADDR_LEN];
48 };
49
50 struct ip6_ext_header {
51 u_int8 next_hdr;
52 u_int8 hdr_len;
53
54 /* Here must be options */
55 };
56
57 struct ip6_ident {
58 u_int32 magic;
59 #define IP6_MAGIC 0x0306e77e
60 u_int8 flow_lbl[3];
61 struct ip_addr L3_src;
62 };
63
64 struct ip6_data {
65 u_int8 priority :4;
66 };
67
68 /* protos */
69
70 void ip6_init(void);
71 FUNC_DECODER(decode_ip6);
72 FUNC_DECODER(decode_ip6_ext);
73 FUNC_INJECTOR(inject_ip6);
74 static size_t ip6_create_ident(void **i, struct packet_object *po);
75 static int ip6_match(void *ident_s, void *ident_c);
76 static void ip6_create_session(struct ec_session **s, struct packet_object *po);
77
78 /*******************************************/
79
80 /*
81 * this function is the initializer.
82 * it adds the entry in the table of registered decoder
83 */
84
85 void __init ip6_init(void)
86 {
87 add_decoder(NET_LAYER, LL_TYPE_IP6, decode_ip6);
88 add_decoder(PROTO_LAYER, NL_TYPE_IP6, decode_ip6);
89 add_decoder(NET6_LAYER, LO6_TYPE_HBH, decode_ip6_ext);
90 add_decoder(NET6_LAYER, LO6_TYPE_RT, decode_ip6_ext);
91 add_decoder(NET6_LAYER, LO6_TYPE_DST, decode_ip6_ext);
92
93 add_injector(CHAIN_LINKED, IP6_MAGIC, inject_ip6);
94 }
95
96
97 FUNC_DECODER(decode_ip6)
98 {
99 FUNC_DECODER_PTR(next_decoder);
100 struct ip6_header *ip6;
101 struct ec_session *s;
102 void *ident;
103
104 ip6 = (struct ip6_header *)DECODE_DATA;
105
106 if (ip6->payload_len == 0) {
107 DEBUG_MSG("IPv6 jumbogram, Hop-By-Hop header should follow");
108 }
109 DECODED_LEN = IP6_HDR_LEN;
110
111 /* IP addresses */
112 ip_addr_init(&PACKET->L3.src, AF_INET6, (u_char *)&ip6->saddr);
113 ip_addr_init(&PACKET->L3.dst, AF_INET6, (u_char *)&ip6->daddr);
114
115 /* this is needed at upper layer to calculate the tcp payload size */
116 PACKET->L3.payload_len = ntohs(ip6->payload_len);
117
118 /* other relevant infos */
119 PACKET->L3.header = (u_char *)DECODE_DATA;
120 PACKET->L3.len = DECODED_LEN;
121
122 PACKET->L3.proto = htons(LL_TYPE_IP6);
123 PACKET->L3.ttl = ip6->hop_limit;
124
125 if(PACKET->fwd_packet == NULL) {
126 EXECUTE(EC_GBL_SNIFF->check_forwarded, PACKET);
127 /* if it is already forwarded */
128 if(PACKET->flags & PO_FORWARDED)
129 return NULL;
130 EXECUTE(EC_GBL_SNIFF->set_forwardable, PACKET);
131 PACKET->fwd_packet = (u_char *)DECODE_DATA;
132 PACKET->fwd_len = PACKET->L3.payload_len + DECODED_LEN;
133 }
134
135 /* calculate if the dest is local or not */
136 switch (ip_addr_is_local(&PACKET->L3.src, NULL)) {
137 case E_SUCCESS:
138 PACKET->PASSIVE.flags &= ~(FP_HOST_NONLOCAL);
139 PACKET->PASSIVE.flags |= FP_HOST_LOCAL;
140 break;
141 case -E_NOTFOUND:
142 PACKET->PASSIVE.flags &= ~FP_HOST_LOCAL;
143 PACKET->PASSIVE.flags |= FP_HOST_NONLOCAL;
144 break;
145 case -E_INVALID:
146 PACKET->PASSIVE.flags = FP_UNKNOWN;
147 break;
148 }
149
150 next_decoder = get_decoder(NET6_LAYER, ip6->next_hdr);
151 if(next_decoder == NULL) {
152 PACKET->L3.options = NULL;
153 PACKET->L3.optlen = 0;
154 next_decoder = get_decoder(PROTO_LAYER, ip6->next_hdr);
155 } else {
156 PACKET->L3.options = (u_char *)&ip6[1];
157 }
158
159 /* HOOK POINT: HOOK_PACKET_IP6 */
160 hook_point(HOOK_PACKET_IP6, po);
161
162 if(!EC_GBL_OPTIONS->unoffensive && !EC_GBL_OPTIONS->read) {
163 ip6_create_ident(&ident, PACKET);
164
165 if(session_get(&s, ident, sizeof(struct ip6_ident)) == -E_NOTFOUND) {
166 ip6_create_session(&s, PACKET);
167 session_put(s);
168 }
169 SAFE_FREE(ident);
170
171 SESSION_PASSTHRU(s, PACKET);
172 }
173
174 /* passing the packet to options or upper-layer decoder */
175 EXECUTE_DECODER(next_decoder);
176
177 /*
178 * External L3 header sets itself
179 * as the packet to be forwarded.
180 */
181 /* XXX - recheck this */
182 if(!EC_GBL_OPTIONS->unoffensive && !EC_GBL_OPTIONS->read && (PACKET->flags & PO_FORWARDABLE)) {
183 if(PACKET->flags & PO_MODIFIED) {
184 ORDER_ADD_SHORT(ip6->payload_len, PACKET->DATA.delta);
185
186 /*
187 * In case some upper level encapsulated ip6 decoder
188 * modified it ... (required for ip6 in ip6 encapsulation)
189 */
190 PACKET->L3.header = (u_char*)ip6;
191 PACKET->L3.len = IP6_HDR_LEN;
192 PACKET->L3.payload_len = ntohs(ip6->payload_len);
193
194 PACKET->fwd_len = PACKET->L3.payload_len + PACKET->L3.len;
195 }
196 }
197
198 return NULL;
199 }
200
201 /* XXX - dirty stuff just to make things work.
202 * Rewrite it to handle extension headers (if needed).
203 */
204 FUNC_DECODER(decode_ip6_ext)
205 {
206 FUNC_DECODER_PTR(next_decoder);
207 struct ip6_ext_header *ext_hdr;
208
209 ext_hdr = (struct ip6_ext_header *)DECODE_DATA;
210 PACKET->L3.optlen += ext_hdr->hdr_len + 1;
211 DECODED_LEN = ext_hdr->hdr_len + 1;
212
213 next_decoder = get_decoder(NET6_LAYER, ext_hdr->next_hdr);
214 if(next_decoder == NULL) {
215 next_decoder = get_decoder(PROTO_LAYER, ext_hdr->next_hdr);
216 }
217
218 EXECUTE_DECODER(next_decoder);
219
220 return NULL;
221 }
222
223 FUNC_INJECTOR(inject_ip6)
224 {
225 struct ip6_header *ip6;
226 struct ip6_ident *ident;
227 struct ip6_data *data;
228 struct ec_session *s = NULL;
229 u_int32 magic;
230 u_int16 plen;
231 u_int16 flen;
232
233 // DEBUG_MSG("inject_ip6");
234
235 /* i think im paranoid */
236 if(LENGTH + sizeof(struct ip6_header) > EC_GBL_IFACE->mtu)
237 return -E_NOTHANDLED;
238
239 /* almost copied from ec_ip.c */
240 PACKET->packet -= sizeof(struct ip6_header);
241 ip6 = (struct ip6_header *)PACKET->packet;
242
243 ip6->version = 6;
244 ip6->next_hdr = PACKET->L4.proto;
245 ip6->hop_limit = 64;
246 memcpy(&ip6->saddr, &PACKET->L3.src.addr, IP6_ADDR_LEN);
247 memcpy(&ip6->daddr, &PACKET->L3.dst.addr, IP6_ADDR_LEN);
248
249 s = PACKET->session;
250 /* Renew session */
251 if(session_get(&s, s->ident, sizeof(struct ip6_ident)) == -E_NOTFOUND)
252 return -E_NOTFOUND;
253
254 ident = s->ident;
255 memcpy(&ip6->flow_lbl, &ident->flow_lbl, 3);
256
257 data = s->data;
258 ip6->priority = data->priority;
259
260 flen = LENGTH;
261 LENGTH += sizeof(struct ip6_header);
262
263 if(s->prev_session != NULL) {
264 PACKET->session = s->prev_session;
265 magic = *(u_int32 *) s->prev_session->ident;
266
267 EXECUTE_INJECTOR(CHAIN_LINKED, magic);
268 }
269
270 plen = EC_GBL_IFACE->mtu - LENGTH < PACKET->DATA.inject_len
271 ? EC_GBL_IFACE->mtu - LENGTH : PACKET->DATA.inject_len;
272 ip6->payload_len = htons(plen);
273
274 PACKET->L3.len = flen + plen;
275 PACKET->L3.header = (u_char *)ip6;
276
277 if(s->prev_session == NULL) {
278 PACKET->fwd_packet = PACKET->packet;
279 PACKET->fwd_len = PACKET->L3.len;
280 }
281
282 return E_SUCCESS;
283 }
284
285 static size_t ip6_create_ident(void **i, struct packet_object *po)
286 {
287 struct ip6_header *ip6;
288 struct ip6_ident *ident;
289
290 SAFE_CALLOC(ident, 1, sizeof(struct ip6_ident));
291
292 ip6 = (struct ip6_header *)po->L3.header;
293
294 ident->magic = IP6_MAGIC;
295 memcpy(&ident->flow_lbl, ip6->flow_lbl, 3);
296 memcpy(&ident->L3_src, &po->L3.src, sizeof(struct ip_addr));
297
298 *i = ident;
299
300 return sizeof(struct ip6_ident);
301 }
302
303 static int ip6_match(void *ident_s, void *ident_c)
304 {
305 struct ip6_ident *ids = ident_s;
306 struct ip6_ident *idc = ident_c;
307
308 if(ids->magic != idc->magic)
309 return 0;
310
311 if(memcmp(&ids->flow_lbl, &idc->flow_lbl, 3))
312 return 0;
313 if(ip_addr_cmp(&ids->L3_src, &idc->L3_src))
314 return 0;
315
316 return 1;
317 }
318
319 static void ip6_create_session(struct ec_session **s, struct packet_object *po)
320 {
321 void *ident;
322
323 DEBUG_MSG("ip6_create_session");
324
325 SAFE_CALLOC(*s, 1, sizeof(struct ec_session));
326 SAFE_CALLOC((*s)->data, 1, sizeof(struct ip6_data));
327
328 (*s)->data_len = sizeof(struct ip6_data);
329 (*s)->ident_len = ip6_create_ident(&ident, po);
330 (*s)->ident = ident;
331 (*s)->match = &ip6_match;
332
333 return;
334 }
335
336 /* EOF */
337
338 // vim:ts=3:expandtab
339