1 /* $Id$ */
2 /****************************************************************************
3  *
4  * Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
5  * Copyright (C) 2007-2013 Sourcefire, Inc.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License Version 2 as
9  * published by the Free Software Foundation.  You may not use, modify or
10  * distribute this program under any other version of the GNU General
11  * Public License.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21  *
22  ****************************************************************************/
23 
24 #include <string.h>
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28 
29 #include "decode.h"
30 #include "reg_test.h"
31 
32 #define FAILURE -1
33 #define SUCCESS 0
34 #define IP6_HEADER_LEN 40
35 
36 /* Version is the first four bits of the uint32_t passed in */
37 #define IP6_VER(x) \
38    (ntohl(x) >> 28)
39 
40 /* The 'Packet' structure is almost always allocated on the stack.
41  * Likewise, return buffers will almost always be aswell.
42  * So, for performance reasons, argument validation can be disabled
43  * and removed from the code at compile time to prevent unecessary extra
44  * conditionals from being checked at run-time. */
45 #define ERR_CHK_LVL  0
46 #if ERR_CHK_LVL == 2
47 #define VALIDATE(x,y) if(!x || !y) return FAILURE;
48 #elif ERR_CHK_LVL == 1
49 #define VALIDATE(x,y) if(!y) return FAILURE;
50 #else
51 #define VALIDATE(x,y)
52 #endif
53 
ip6_ret_src(const Packet * p)54 sfaddr_t *ip6_ret_src(const Packet *p)
55 {
56     VALIDATE(p, 1);
57 
58     return &p->ip6h->ip_addrs->ip_src;
59 }
60 
orig_ip6_ret_src(const Packet * p)61 sfaddr_t *orig_ip6_ret_src(const Packet *p)
62 {
63     VALIDATE(p, 1);
64 
65     return &p->orig_ip6h->ip_addrs->ip_src;
66 }
67 
ip6_ret_dst(const Packet * p)68 sfaddr_t *ip6_ret_dst(const Packet *p)
69 {
70     VALIDATE(p, 1);
71 
72     return &p->ip6h->ip_addrs->ip_dst;
73 }
74 
75 
orig_ip6_ret_dst(const Packet * p)76 sfaddr_t *orig_ip6_ret_dst(const Packet *p)
77 {
78     VALIDATE(p, 1);
79 
80     return &p->orig_ip6h->ip_addrs->ip_dst;
81 }
82 
ip6_ret_toc(const Packet * p)83 uint16_t ip6_ret_toc(const Packet *p)
84 {
85     uint16_t toc;
86     VALIDATE(p,1);
87 
88     toc = (uint16_t)((ntohl(p->ip6h->vcl) & 0x0FF00000) >> 20);
89 
90     return toc;
91 }
92 
orig_ip6_ret_toc(const Packet * p)93 uint16_t orig_ip6_ret_toc(const Packet *p)
94 {
95     uint16_t toc;
96     VALIDATE(p,1);
97 
98     toc = (uint16_t)((ntohl(p->orig_ip6h->vcl) & 0x0FF00000) >> 20);
99     return toc;
100 }
101 
ip6_ret_hops(const Packet * p)102 uint8_t ip6_ret_hops(const Packet *p)
103 {
104 //    VALIDATE(p,1);
105 
106     return p->ip6h->hop_lmt;
107 }
108 
orig_ip6_ret_hops(const Packet * p)109 uint8_t orig_ip6_ret_hops(const Packet *p)
110 {
111 //    VALIDATE(p,1);
112 
113     return p->orig_ip6h->hop_lmt;
114 }
115 
ip6_ret_len(const Packet * p)116 uint16_t ip6_ret_len(const Packet *p)
117 {
118     VALIDATE(p,1);
119 
120     /* The length field does not include the header in IPv6, but does in IPv4.
121      * To make this analogous to IPv4, for Snort's purposes, we need to tack
122      * on the difference. */
123     return p->ip6h->len;
124 }
125 
orig_ip6_ret_len(const Packet * p)126 uint16_t orig_ip6_ret_len(const Packet *p)
127 {
128     VALIDATE(p,1);
129 
130     return p->orig_ip6h->len;
131 }
132 
ip6_ret_id(const Packet * p)133 uint32_t ip6_ret_id(const Packet *p)
134 {
135     IP6Frag *frag_hdr;
136     if (p->ip6_extension_count == 0)
137         return 0;
138 
139     frag_hdr = (IP6Frag*)p->ip6_extensions[p->ip6_frag_index].data;
140 
141     return frag_hdr->ip6f_ident;
142 }
143 
orig_ip6_ret_id(const Packet * p)144 uint32_t orig_ip6_ret_id(const Packet *p)
145 {
146 // XXX-IPv6 "NOT YET IMPLEMENTED - IP6 identification"
147     return 0;
148 }
149 
ip6_ret_next(const Packet * p)150 uint8_t ip6_ret_next(const Packet *p)
151 {
152     VALIDATE(p,1);
153     return p->ip6h->next;
154 }
155 
orig_ip6_ret_next(const Packet * p)156 uint8_t orig_ip6_ret_next(const Packet *p)
157 {
158     VALIDATE(p,1);
159     return p->orig_ip6h->next;
160 }
161 
ip6_ret_off(const Packet * p)162 uint16_t ip6_ret_off(const Packet *p)
163 {
164     IP6Frag *frag_hdr;
165     if (p->ip6_extension_count == 0)
166         return 0;
167 
168     frag_hdr = (IP6Frag *)p->ip6_extensions[p->ip6_frag_index].data;
169 
170     return frag_hdr->ip6f_offlg;
171 }
172 
orig_ip6_ret_off(const Packet * p)173 uint16_t orig_ip6_ret_off(const Packet *p)
174 {
175 // XXX-IPv6 "NOT YET IMPLEMENTED - IP6 frag offset"
176     return 0;
177 }
178 
ip6_ret_ver(const Packet * p)179 uint8_t ip6_ret_ver(const Packet *p)
180 {
181     return (uint8_t)IP6_VER(p->ip6h->vcl);
182 }
183 
orig_ip6_ret_ver(const Packet * p)184 uint8_t orig_ip6_ret_ver(const Packet *p)
185 {
186     return (uint8_t)IP6_VER(p->orig_ip6h->vcl);
187 }
188 
ip4_ret_dst(const Packet * p)189 sfaddr_t *ip4_ret_dst(const Packet *p)
190 {
191     VALIDATE(p,1);
192     return &p->ip4h->ip_addrs->ip_dst;
193 }
194 
orig_ip4_ret_dst(const Packet * p)195 sfaddr_t *orig_ip4_ret_dst(const Packet *p)
196 {
197     VALIDATE(p,1);
198     return &p->orig_ip4h->ip_addrs->ip_dst;
199 }
200 
ip4_ret_src(const Packet * p)201 sfaddr_t *ip4_ret_src(const Packet *p)
202 {
203     VALIDATE(p,1);
204     return &p->ip4h->ip_addrs->ip_src;
205 }
206 
orig_ip4_ret_src(const Packet * p)207 sfaddr_t *orig_ip4_ret_src(const Packet *p)
208 {
209     VALIDATE(p,1);
210     return &p->orig_ip4h->ip_addrs->ip_src;
211 }
212 
ip4_ret_tos(const Packet * p)213 uint16_t ip4_ret_tos(const Packet *p)
214 {
215    VALIDATE(p,1);
216 
217    return p->ip4h->ip_tos;
218 }
219 
orig_ip4_ret_tos(const Packet * p)220 uint16_t orig_ip4_ret_tos(const Packet *p)
221 {
222    VALIDATE(p,1);
223 
224    return p->orig_ip4h->ip_tos;
225 }
226 
ip4_ret_ttl(const Packet * p)227 uint8_t ip4_ret_ttl(const Packet *p)
228 {
229     VALIDATE(p,1);
230 
231     return p->ip4h->ip_ttl;
232 }
233 
orig_ip4_ret_ttl(const Packet * p)234 uint8_t orig_ip4_ret_ttl(const Packet *p)
235 {
236     VALIDATE(p,1);
237 
238     return p->orig_ip4h->ip_ttl;
239 }
240 
ip4_ret_len(const Packet * p)241 uint16_t ip4_ret_len(const Packet *p)
242 {
243     VALIDATE(p,1);
244 
245     return p->ip4h->ip_len;
246 }
247 
orig_ip4_ret_len(const Packet * p)248 uint16_t orig_ip4_ret_len(const Packet *p)
249 {
250     VALIDATE(p,1);
251 
252     return p->orig_ip4h->ip_len;
253 }
254 
ip4_ret_id(const Packet * p)255 uint32_t ip4_ret_id(const Packet *p)
256 {
257     VALIDATE(p,1);
258 
259     return (uint32_t)p->ip4h->ip_id;
260 }
261 
orig_ip4_ret_id(const Packet * p)262 uint32_t orig_ip4_ret_id(const Packet *p)
263 {
264     VALIDATE(p,1);
265 
266     return (uint32_t)p->orig_ip4h->ip_id;
267 }
268 
ip4_ret_proto(const Packet * p)269 uint8_t ip4_ret_proto(const Packet *p)
270 {
271     // VALIDATION()
272 
273     return p->ip4h->ip_proto;
274 }
275 
orig_ip4_ret_proto(const Packet * p)276 uint8_t orig_ip4_ret_proto(const Packet *p)
277 {
278     // VALIDATION()
279 
280     return p->orig_ip4h->ip_proto;
281 }
282 
ip4_ret_off(const Packet * p)283 uint16_t ip4_ret_off(const Packet *p)
284 {
285     return p->ip4h->ip_off;
286 }
287 
orig_ip4_ret_off(const Packet * p)288 uint16_t orig_ip4_ret_off(const Packet *p)
289 {
290     return p->orig_ip4h->ip_off;
291 }
292 
ip4_ret_ver(const Packet * p)293 uint8_t ip4_ret_ver(const Packet *p)
294 {
295     return IP_VER(p->iph);
296 }
297 
orig_ip4_ret_ver(const Packet * p)298 uint8_t orig_ip4_ret_ver(const Packet *p)
299 {
300     return IP_VER(p->orig_iph);
301 }
302 
ip4_ret_hlen(const Packet * p)303 uint8_t ip4_ret_hlen(const Packet *p)
304 {
305     return IP_HLEN(p->iph);
306 }
307 
orig_ip4_ret_hlen(const Packet * p)308 uint8_t orig_ip4_ret_hlen(const Packet *p)
309 {
310     return IP_HLEN(p->orig_iph);
311 }
312 
ip6_ret_hlen(const Packet * p)313 uint8_t ip6_ret_hlen(const Packet *p)
314 {
315     /* Snort is expecting this number to be in terms of 32 bit words */
316     return IP6_HDR_LEN / 4 ;
317 }
318 
orig_ip6_ret_hlen(const Packet * p)319 uint8_t orig_ip6_ret_hlen(const Packet *p)
320 {
321     return IP6_HDR_LEN / 4;
322 }
323 
324 IPH_API ip4 =
325 {
326    ip4_ret_src,
327    ip4_ret_dst,
328    ip4_ret_tos,
329    ip4_ret_ttl,
330    ip4_ret_len,
331    ip4_ret_id,
332    ip4_ret_proto,
333    ip4_ret_off,
334    ip4_ret_ver,
335    ip4_ret_hlen,
336 
337    orig_ip4_ret_src,
338    orig_ip4_ret_dst,
339    orig_ip4_ret_tos,
340    orig_ip4_ret_ttl,
341    orig_ip4_ret_len,
342    orig_ip4_ret_id,
343    orig_ip4_ret_proto,
344    orig_ip4_ret_off,
345    orig_ip4_ret_ver,
346    orig_ip4_ret_hlen,
347 
348    IPH_API_V4
349 };
350 
351 IPH_API ip6 =
352 {
353    ip6_ret_src,
354    ip6_ret_dst,
355    ip6_ret_toc,
356    ip6_ret_hops,
357    ip6_ret_len,
358    ip6_ret_id,
359    ip6_ret_next,
360    ip6_ret_off,
361    ip6_ret_ver,
362    ip6_ret_hlen,
363 
364    orig_ip6_ret_src,
365    orig_ip6_ret_dst,
366    orig_ip6_ret_toc,
367    orig_ip6_ret_hops,
368    orig_ip6_ret_len,
369    orig_ip6_ret_id,
370    orig_ip6_ret_next,
371    orig_ip6_ret_off,
372    orig_ip6_ret_ver,
373    orig_ip6_ret_hlen,
374 
375    IPH_API_V6
376 };
377 
_set_callbacks(struct _Packet * p,int family,char orig)378 static inline void _set_callbacks(struct _Packet *p, int family, char orig)
379 {
380     if ( !orig )
381     {
382         if(family == AF_INET)
383             p->iph_api = &ip4;
384         else
385             p->iph_api = &ip6;
386 
387         p->family = family;
388     }
389     else
390     {
391         if(family == AF_INET)
392             p->orig_iph_api = &ip4;
393         else
394             p->orig_iph_api = &ip6;
395 
396         p->orig_family = family;
397     }
398 }
399 
set_callbacks(struct _Packet * p,int family,char orig)400 void set_callbacks(struct _Packet *p, int family, char orig)
401 {
402     _set_callbacks(p, family, orig);
403 }
404 
sfiph_build(Packet * p,const void * hdr,int family)405 void sfiph_build(Packet *p, const void *hdr, int family)
406 {
407     IP6RawHdr *hdr6;
408     IPHdr *hdr4;
409 
410     if(!p || !hdr)
411         return;
412 
413     /* If family is already set, we've been here before.
414      * That means this is a nested IP.  */
415     if (p->family != NO_IP)
416     {
417         memcpy(&p->outer_ips, &p->inner_ips, sizeof(p->outer_ips));
418         if (p->iph_api->ver == IPH_API_V4)
419         {
420             memcpy(&p->outer_ip4h, &p->inner_ip4h, sizeof(p->outer_ip4h) - sizeof(p->outer_ip4h.ip_addrs));
421             p->outer_ip4h.ip_addrs = &p->outer_ips;
422         }
423         else if (p->iph_api->ver == IPH_API_V6)
424         {
425             memcpy(&p->outer_ip6h, &p->inner_ip6h, sizeof(p->outer_ip6h) - sizeof(p->outer_ip6h.ip_addrs));
426             p->outer_ip6h.ip_addrs = &p->outer_ips;
427         }
428 
429         p->outer_iph_api = p->iph_api;
430         p->outer_family = p->family;
431     }
432 
433     _set_callbacks(p, family, CALLBACK_IP);
434 
435     if(family == AF_INET)
436     {
437         hdr4 = (IPHdr*)hdr;
438 
439         /* The struct Snort uses is identical to the actual IP4 struct,
440          * with the exception of the IP addresses. Copy over everything but
441          * the IPs */
442         memcpy(&p->inner_ip4h, hdr4, sizeof(IPHdr) - 8);
443 #ifdef HAVE_DAQ_REAL_ADDRESSES
444         if (p->outer_family != NO_IP || !(p->pkth->flags & DAQ_PKT_FLAG_REAL_ADDRESSES))
445         {
446 #endif
447             sfip_set_raw(&p->inner_ips.ip_src, &hdr4->ip_src, AF_INET);
448             sfip_set_raw(&p->inner_ips.ip_dst, &hdr4->ip_dst, AF_INET);
449 #ifdef HAVE_DAQ_REAL_ADDRESSES
450         }
451         else
452         {
453             sfip_set_raw(&p->inner_ips.ip_src, p->pkth->real_sIP.s6_addr, (p->pkth->flags & DAQ_PKT_FLAG_REAL_SIP_V6) ? AF_INET6 : AF_INET);
454             sfip_set_raw(&p->inner_ips.ip_dst, p->pkth->real_dIP.s6_addr, (p->pkth->flags & DAQ_PKT_FLAG_REAL_DIP_V6) ? AF_INET6 : AF_INET);
455         }
456 #endif
457         p->inner_ip4h.ip_addrs = &p->inner_ips;
458         p->actual_ip_len = ntohs(p->inner_ip4h.ip_len);
459         p->ip4h = &p->inner_ip4h;
460     }
461     else
462     {
463         hdr6 = (IP6RawHdr*)hdr;
464 
465         /* The struct Snort uses is identical to the actual IP6 struct,
466          * with the exception of the IP addresses. Copy over everything but
467          * the IPs*/
468         memcpy(&p->inner_ip6h, hdr6, sizeof(IP6RawHdr) - 32);
469 #ifdef HAVE_DAQ_REAL_ADDRESSES
470         if (p->outer_family != NO_IP || !(p->pkth->flags & DAQ_PKT_FLAG_REAL_ADDRESSES))
471         {
472 #endif
473             sfip_set_raw(&p->inner_ips.ip_src, &hdr6->ip6_src, family);
474             sfip_set_raw(&p->inner_ips.ip_dst, &hdr6->ip6_dst, family);
475 #ifdef HAVE_DAQ_REAL_ADDRESSES
476         }
477         else
478         {
479             sfip_set_raw(&p->inner_ips.ip_src, p->pkth->real_sIP.s6_addr, (p->pkth->flags & DAQ_PKT_FLAG_REAL_SIP_V6) ? AF_INET6 : AF_INET);
480             sfip_set_raw(&p->inner_ips.ip_dst, p->pkth->real_dIP.s6_addr, (p->pkth->flags & DAQ_PKT_FLAG_REAL_DIP_V6) ? AF_INET6 : AF_INET);
481         }
482 #endif
483         p->inner_ip6h.ip_addrs = &p->inner_ips;
484         p->actual_ip_len = ntohs(p->inner_ip6h.len) + IP6_HDR_LEN;
485         p->ip6h = &p->inner_ip6h;
486     }
487 #ifdef REG_TEST
488     if (rt_ip_increment)
489     {
490         uint32_t* addr;
491         addr = sfaddr_get_ip4_ptr(&p->inner_ips.ip_src);
492         *addr = htonl(ntohl(*addr) + rt_ip_increment);
493         addr = sfaddr_get_ip4_ptr(&p->inner_ips.ip_dst);
494         *addr = htonl(ntohl(*addr) + rt_ip_increment);
495     }
496 #endif
497 }
498 
sfiph_orig_build(Packet * p,const void * hdr,int family)499 void sfiph_orig_build(Packet *p, const void *hdr, int family)
500 {
501     IP6RawHdr *hdr6;
502     IPHdr *hdr4;
503 
504     if(!p || !hdr)
505         return;
506 
507     /* If iph_api is already set, we've been here before.
508      * That means this is a nested IP.  */
509     if (p->orig_iph_api)
510     {
511         memcpy(&p->outer_orig_ips, &p->inner_orig_ips, sizeof(p->outer_orig_ips));
512         if (p->orig_iph_api->ver == IPH_API_V4)
513         {
514             memcpy(&p->outer_orig_ip4h, &p->inner_orig_ip4h,
515                    sizeof(p->outer_orig_ip4h) - sizeof(p->outer_orig_ip4h.ip_addrs));
516             p->outer_orig_ip4h.ip_addrs = &p->outer_orig_ips;
517             p->outer_orig_iph_api = p->orig_iph_api;
518         }
519         else if (p->orig_iph_api->ver == IPH_API_V6)
520         {
521             memcpy(&p->outer_orig_ip6h, &p->inner_orig_ip6h,
522                    sizeof(p->outer_orig_ip6h) - sizeof(p->outer_orig_ip6h.ip_addrs));
523             p->outer_orig_ip6h.ip_addrs = &p->outer_orig_ips;
524             p->outer_orig_iph_api = p->orig_iph_api;
525         }
526     }
527 
528     _set_callbacks(p, family, CALLBACK_ICMP_ORIG);
529 
530     if(family == AF_INET)
531     {
532         hdr4 = (IPHdr*)hdr;
533 
534         /* The struct Snort uses is identical to the actual IP6 struct,
535          * with the exception of the IP addresses. Copy over everything but
536          * the IPs */
537         memcpy(&p->inner_orig_ip4h, hdr4, sizeof(IPHdr) - 8);
538         sfip_set_raw(&p->inner_orig_ips.ip_src, &hdr4->ip_src, family);
539         sfip_set_raw(&p->inner_orig_ips.ip_dst, &hdr4->ip_dst, family);
540         p->inner_orig_ip4h.ip_addrs = &p->inner_orig_ips;
541         p->actual_ip_len = ntohs(p->inner_orig_ip4h.ip_len);
542         p->orig_ip4h = &p->inner_orig_ip4h;
543     }
544     else
545     {
546         hdr6 = (IP6RawHdr*)hdr;
547 
548         /* The struct Snort uses is identical to the actual IP6 struct,
549          * with the exception of the IP addresses. Copy over everything but
550          * the IPs*/
551         memcpy(&p->inner_orig_ip6h, hdr6, sizeof(IP6RawHdr) - 32);
552         sfip_set_raw(&p->inner_orig_ips.ip_src, &hdr6->ip6_src, family);
553         sfip_set_raw(&p->inner_orig_ips.ip_dst, &hdr6->ip6_dst, family);
554         p->inner_orig_ip6h.ip_addrs = &p->inner_orig_ips;
555         p->actual_ip_len = ntohs(p->inner_orig_ip6h.len) + IP6_HDR_LEN;
556         p->orig_ip6h = &p->inner_orig_ip6h;
557     }
558 }
559 
560 #ifdef TESTER
main()561 int main()
562 {
563     Packet p;
564     IP4Hdr i4;
565     IP6Hdr i6;
566 
567     /* This test assumes we get an IPv4 packet and verifies
568      * that the correct callbacks are setup, and they return
569      * the correct values. */
570 
571     _set_callbacks(&p, AF_INET, CALLBACK_IP);
572 
573     /* Same test as above, but with IPv6 */
574     _set_callbacks(&p, AF_INET6, CALLBACK_IP);
575 
576     return 0;
577 }
578 #endif
579