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