1 /* $Id$ */
2 /****************************************************************************
3 *
4 * Copyright (C) 2007-2009 Sourcefire, Inc.
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 Version 2 as
8 * published by the Free Software Foundation. You may not use, modify or
9 * distribute this program under any other version of the GNU General
10 * Public License.
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, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 *
21 ****************************************************************************/
22
23 #include <string.h>
24 #include "decode.h"
25
26 #ifdef SUP_IP6
27
28 #define FAILURE -1
29 #define SUCCESS 0
30 #define IP6_HEADER_LEN 40
31
32 /* Version is the first four bits of the uint32_t passed in */
33 #define IP6_VER(x) ((x) >> 28)
34
35 /* The 'Packet' structure is almost always allocated on the stack.
36 * Likewise, return buffers will almost always be aswell.
37 * So, for performance reasons, argument validation can be disabled
38 * and removed from the code at compile time to prevent unecessary extra
39 * conditionals from being checked at run-time. */
40 #if ERR_CHK_LVL == 2
41 #define VALIDATE(x,y) if(!x || !y) return FAILURE;
42 #elif ERR_CHK_LVL == 1
43 #define VALIDATE(x,y) if(!y) return FAILURE;
44 #else
45 #define VALIDATE(x,y)
46 #endif
47
ip6_ret_src(Packet * p)48 sfip_t *ip6_ret_src(Packet *p)
49 {
50 VALIDATE(p, 1);
51
52 return &p->ip6h->ip_src;
53 }
54
orig_ip6_ret_src(Packet * p)55 sfip_t *orig_ip6_ret_src(Packet *p)
56 {
57 VALIDATE(p, 1);
58
59 return &p->orig_ip6h->ip_src;
60 }
61
ip6_ret_dst(Packet * p)62 sfip_t *ip6_ret_dst(Packet *p)
63 {
64 VALIDATE(p, 1);
65
66 return &p->ip6h->ip_dst;
67 }
68
69
orig_ip6_ret_dst(Packet * p)70 sfip_t *orig_ip6_ret_dst(Packet *p)
71 {
72 VALIDATE(p, 1);
73
74 return &p->orig_ip6h->ip_dst;
75 }
76
ip6_ret_toc(Packet * p)77 uint16_t ip6_ret_toc(Packet *p)
78 {
79 uint16_t toc;
80 VALIDATE(p,1);
81
82 toc = (uint16_t)((ntohl(p->ip6h->vcl) & 0x0FF00000) >> 20);
83
84 return toc;
85 }
86
orig_ip6_ret_toc(Packet * p)87 uint16_t orig_ip6_ret_toc(Packet *p)
88 {
89 uint16_t toc;
90 VALIDATE(p,1);
91
92 toc = (uint16_t)((ntohl(p->orig_ip6h->vcl) & 0x0FF00000) >> 20);
93 return toc;
94 }
95
ip6_ret_hops(Packet * p)96 uint8_t ip6_ret_hops(Packet *p)
97 {
98 // VALIDATE(p,1);
99
100 return p->ip6h->hop_lmt;
101 }
orig_ip6_ret_hops(Packet * p)102 uint8_t orig_ip6_ret_hops(Packet *p)
103 {
104 // VALIDATE(p,1);
105
106 return p->orig_ip6h->hop_lmt;
107 }
108
ip6_ret_len(Packet * p)109 uint16_t ip6_ret_len(Packet *p)
110 {
111 VALIDATE(p,1);
112
113 /* The length field does not include the header in IPv6, but does in IPv4.
114 * To make this analogous to IPv4, for Snort's purposes, we need to tack
115 * on the difference. */
116 return p->ip6h->len;
117 }
118
orig_ip6_ret_len(Packet * p)119 uint16_t orig_ip6_ret_len(Packet *p)
120 {
121 VALIDATE(p,1);
122
123 return p->orig_ip6h->len;
124 }
125
ip6_ret_id(Packet * p)126 uint32_t ip6_ret_id(Packet *p)
127 {
128 IP6Frag *frag_hdr;
129 if (p->ip6_extension_count == 0)
130 return 0;
131
132 frag_hdr = (IP6Frag*)p->ip6_extensions[p->ip6_frag_index].data;
133
134 return frag_hdr->ip6f_ident;
135 }
136
orig_ip6_ret_id(Packet * p)137 uint32_t orig_ip6_ret_id(Packet *p)
138 {
139 // XXX-IPv6 "NOT YET IMPLEMENTED - IP6 identification"
140 return 0;
141 }
142
ip6_ret_next(Packet * p)143 uint8_t ip6_ret_next(Packet *p)
144 {
145 VALIDATE(p,1);
146 return p->ip6h->next;
147 }
148
orig_ip6_ret_next(Packet * p)149 uint8_t orig_ip6_ret_next(Packet *p)
150 {
151 VALIDATE(p,1);
152 return p->orig_ip6h->next;
153 }
154
ip6_ret_off(Packet * p)155 uint16_t ip6_ret_off(Packet *p)
156 {
157 IP6Frag *frag_hdr;
158 if (p->ip6_extension_count == 0)
159 return 0;
160
161 frag_hdr = (IP6Frag *)p->ip6_extensions[p->ip6_frag_index].data;
162
163 return frag_hdr->ip6f_offlg;
164 }
165
orig_ip6_ret_off(Packet * p)166 uint16_t orig_ip6_ret_off(Packet *p)
167 {
168 // XXX-IPv6 "NOT YET IMPLEMENTED - IP6 frag offset"
169 return 0;
170 }
171
ip6_ret_ver(Packet * p)172 uint8_t ip6_ret_ver(Packet *p)
173 {
174 return (uint8_t)IP6_VER(p->ip6h->vcl);
175 }
176
orig_ip6_ret_ver(Packet * p)177 uint8_t orig_ip6_ret_ver(Packet *p)
178 {
179 return (uint8_t)IP6_VER(p->orig_ip6h->vcl);
180 }
181
ip4_ret_dst(Packet * p)182 sfip_t *ip4_ret_dst(Packet *p)
183 {
184 VALIDATE(p,1);
185 return &p->ip4h->ip_dst;
186 }
187
orig_ip4_ret_dst(Packet * p)188 sfip_t *orig_ip4_ret_dst(Packet *p)
189 {
190 VALIDATE(p,1);
191 return &p->orig_ip4h->ip_dst;
192 }
193
ip4_ret_src(Packet * p)194 sfip_t *ip4_ret_src(Packet *p)
195 {
196 VALIDATE(p,1);
197 return &p->ip4h->ip_src;
198 }
199
orig_ip4_ret_src(Packet * p)200 sfip_t *orig_ip4_ret_src(Packet *p)
201 {
202 VALIDATE(p,1);
203 return &p->orig_ip4h->ip_src;
204 }
205
ip4_ret_tos(Packet * p)206 uint16_t ip4_ret_tos(Packet *p)
207 {
208 VALIDATE(p,1);
209
210 return p->ip4h->ip_tos;
211 }
212
orig_ip4_ret_tos(Packet * p)213 uint16_t orig_ip4_ret_tos(Packet *p)
214 {
215 VALIDATE(p,1);
216
217 return p->orig_ip4h->ip_tos;
218 }
219
ip4_ret_ttl(Packet * p)220 uint8_t ip4_ret_ttl(Packet *p)
221 {
222 VALIDATE(p,1);
223
224 return p->ip4h->ip_ttl;
225 }
226
orig_ip4_ret_ttl(Packet * p)227 uint8_t orig_ip4_ret_ttl(Packet *p)
228 {
229 VALIDATE(p,1);
230
231 return p->orig_ip4h->ip_ttl;
232 }
233
ip4_ret_len(Packet * p)234 uint16_t ip4_ret_len(Packet *p)
235 {
236 VALIDATE(p,1);
237
238 return p->ip4h->ip_len;
239 }
240
orig_ip4_ret_len(Packet * p)241 uint16_t orig_ip4_ret_len(Packet *p)
242 {
243 VALIDATE(p,1);
244
245 return p->orig_ip4h->ip_len;
246 }
247
ip4_ret_id(Packet * p)248 uint32_t ip4_ret_id(Packet *p)
249 {
250 VALIDATE(p,1);
251
252 return (uint32_t)p->ip4h->ip_id;
253 }
254
orig_ip4_ret_id(Packet * p)255 uint32_t orig_ip4_ret_id(Packet *p)
256 {
257 VALIDATE(p,1);
258
259 return (uint32_t)p->orig_ip4h->ip_id;
260 }
261
ip4_ret_proto(Packet * p)262 uint8_t ip4_ret_proto(Packet *p)
263 {
264 // VALIDATION()
265
266 return p->ip4h->ip_proto;
267 }
268
orig_ip4_ret_proto(Packet * p)269 uint8_t orig_ip4_ret_proto(Packet *p)
270 {
271 // VALIDATION()
272
273 return p->orig_ip4h->ip_proto;
274 }
275
ip4_ret_off(Packet * p)276 uint16_t ip4_ret_off(Packet *p)
277 {
278 return p->ip4h->ip_off;
279 }
280
orig_ip4_ret_off(Packet * p)281 uint16_t orig_ip4_ret_off(Packet *p)
282 {
283 return p->orig_ip4h->ip_off;
284 }
285
ip4_ret_ver(Packet * p)286 uint8_t ip4_ret_ver(Packet *p)
287 {
288 return IP_VER(p->iph);
289 }
290
orig_ip4_ret_ver(Packet * p)291 uint8_t orig_ip4_ret_ver(Packet *p)
292 {
293 return IP_VER(p->orig_iph);
294 }
295
ip4_ret_hlen(Packet * p)296 uint8_t ip4_ret_hlen(Packet *p)
297 {
298 return IP_HLEN(p->iph);
299 }
300
orig_ip4_ret_hlen(Packet * p)301 uint8_t orig_ip4_ret_hlen(Packet *p)
302 {
303 return IP_HLEN(p->orig_iph);
304 }
305
ip6_ret_hlen(Packet * p)306 uint8_t ip6_ret_hlen(Packet *p)
307 {
308 /* Snort is expecting this number to be in terms of 32 bit words */
309 return IP6_HDR_LEN / 4 ;
310 }
311
orig_ip6_ret_hlen(Packet * p)312 uint8_t orig_ip6_ret_hlen(Packet *p)
313 {
314 return IP6_HDR_LEN / 4;
315 }
316
sfiph_build(Packet * p,const void * hdr,int family)317 void sfiph_build(Packet *p, const void *hdr, int family)
318 {
319 IP6RawHdr *hdr6;
320 IPHdr *hdr4;
321
322 if(!p || !hdr)
323 return;
324
325 /* If family is already set, we've been here before.
326 * That means this is a nested IP. */
327 if (p->family != NO_IP)
328 {
329 if (p->iph_api->ver == IPH_API_V4)
330 memcpy(&p->outer_ip4h, &p->inner_ip4h, sizeof(IP4Hdr));
331 else if (p->iph_api->ver == IPH_API_V6)
332 memcpy(&p->outer_ip6h, &p->inner_ip6h, sizeof(IP6Hdr));
333
334 p->outer_iph_api = p->iph_api;
335 p->outer_family = p->family;
336 }
337
338 set_callbacks(p, family, CALLBACK_IP);
339
340 if(family == AF_INET)
341 {
342 hdr4 = (IPHdr*)hdr;
343
344 /* The struct Snort uses is identical to the actual IP6 struct,
345 * with the exception of the IP addresses. Copy over everything but
346 * the IPs */
347 memcpy(&p->inner_ip4h, hdr4, sizeof(IPHdr) - 8);
348 sfip_set_raw(&p->inner_ip4h.ip_src, &hdr4->ip_src, p->family);
349 sfip_set_raw(&p->inner_ip4h.ip_dst, &hdr4->ip_dst, p->family);
350 p->actual_ip_len = ntohs(p->inner_ip4h.ip_len);
351 p->ip4h = &p->inner_ip4h;
352 }
353 else
354 {
355 hdr6 = (IP6RawHdr*)hdr;
356
357 /* The struct Snort uses is identical to the actual IP6 struct,
358 * with the exception of the IP addresses. Copy over everything but
359 * the IPs*/
360 memcpy(&p->inner_ip6h, hdr6, sizeof(IP6RawHdr) - 32);
361 sfip_set_raw(&p->inner_ip6h.ip_src, &hdr6->ip6_src, p->family);
362 sfip_set_raw(&p->inner_ip6h.ip_dst, &hdr6->ip6_dst, p->family);
363 p->actual_ip_len = ntohs(p->inner_ip6h.len) + IP6_HDR_LEN;
364 p->ip6h = &p->inner_ip6h;
365 }
366 }
367
sfiph_orig_build(Packet * p,const void * hdr,int family)368 void sfiph_orig_build(Packet *p, const void *hdr, int family)
369 {
370 IP6RawHdr *hdr6;
371 IPHdr *hdr4;
372
373 if(!p || !hdr)
374 return;
375
376 /* If iph_api is already set, we've been here before.
377 * That means this is a nested IP. */
378 if (p->orig_iph_api && (p->orig_iph_api->ver == IPH_API_V4))
379 {
380 memcpy(&p->outer_orig_ip4h, &p->inner_orig_ip4h, sizeof(IP4Hdr));
381 p->outer_orig_iph_api = p->orig_iph_api;
382 }
383 else if (p->orig_iph_api && (p->orig_iph_api->ver == IPH_API_V6))
384 {
385 memcpy(&p->outer_orig_ip6h, &p->inner_orig_ip6h, sizeof(IP6Hdr));
386 p->outer_orig_iph_api = p->orig_iph_api;
387 }
388
389 set_callbacks(p, family, CALLBACK_ICMP_ORIG);
390
391 if(family == AF_INET)
392 {
393 hdr4 = (IPHdr*)hdr;
394
395 /* The struct Snort uses is identical to the actual IP6 struct,
396 * with the exception of the IP addresses. Copy over everything but
397 * the IPs */
398 memcpy(&p->inner_orig_ip4h, hdr4, sizeof(IPHdr) - 8);
399 sfip_set_raw(&p->inner_orig_ip4h.ip_src, &hdr4->ip_src, p->family);
400 sfip_set_raw(&p->inner_orig_ip4h.ip_dst, &hdr4->ip_dst, p->family);
401 p->actual_ip_len = ntohs(p->inner_orig_ip4h.ip_len);
402 p->orig_ip4h = &p->inner_orig_ip4h;
403 }
404 else
405 {
406 hdr6 = (IP6RawHdr*)hdr;
407
408 /* The struct Snort uses is identical to the actual IP6 struct,
409 * with the exception of the IP addresses. Copy over everything but
410 * the IPs*/
411 memcpy(&p->inner_orig_ip6h, hdr6, sizeof(IP6RawHdr) - 32);
412 sfip_set_raw(&p->inner_orig_ip6h.ip_src, &hdr6->ip6_src, p->family);
413 sfip_set_raw(&p->inner_orig_ip6h.ip_dst, &hdr6->ip6_dst, p->family);
414 p->actual_ip_len = ntohs(p->inner_orig_ip6h.len) + IP6_HDR_LEN;
415 p->orig_ip6h = &p->inner_orig_ip6h;
416 }
417 }
418
419 #ifdef TESTER
main()420 int main()
421 {
422 Packet p;
423 IP4Hdr i4;
424 IP6Hdr i6;
425
426 /* This test assumes we get an IPv4 packet and verifies
427 * that the correct callbacks are setup, and they return
428 * the correct values. */
429
430 set_callbacks(&p, AF_INET, CALLBACK_IP);
431
432 /* Same test as above, but with IPv6 */
433 set_callbacks(&p, AF_INET6, CALLBACK_IP);
434
435 return 0;
436 }
437 #endif
438 #endif /* #ifdef SUP_IP6 */
439