1 /*
2 ** Copyright (C) 1998-2009 Sourcefire, Inc.
3 ** Adam Keeton
4 ** Kevin Liu <kliu@sourcefire.com>
5 *
6 ** $ID: $
7 **
8 ** This program is free software; you can redistribute it and/or modify
9 ** it under the terms of the GNU General Public License Version 2 as
10 ** published by the Free Software Foundation.  You may not use, modify or
11 ** distribute this program under any other version of the GNU General
12 ** Public License.
13 **
14 ** This program is distributed in the hope that it will be useful,
15 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 ** GNU General Public License for more details.
18 **
19 ** You should have received a copy of the GNU General Public License
20 ** along with this program; if not, write to the Free Software
21 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23 
24 /*
25  * Adam Keeton
26  * sf_ip.h
27  * 11/17/06
28 */
29 
30 #ifndef SF_IP_H
31 #define SF_IP_H
32 
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36 
37 #ifndef WIN32
38 #include <sys/types.h>
39 #include <sys/socket.h>
40 #include <arpa/inet.h>
41 #endif
42 
43 #ifdef SF_IP_TEST
44 #define INLINE inline
45 #else
46 #include "debug.h" /* for INLINE definition */
47 #endif
48 
49 #include "sf_types.h"
50 
51 /* define SFIP_ROBUST to check pointers passed into the sfip libs.
52  * Robustification should not be enabled if the client code is trustworthy.
53  * Namely, if pointers are checked once in the client, or are pointers to
54  * data allocated on the stack, there's no need to check them again here.
55  * The intention is to prevent the same stack-allocated variable from being
56  * checked a dozen different times. */
57 #define SFIP_ROBUST
58 
59 #ifdef SFIP_ROBUST
60 
61 #define ARG_CHECK1(a, z) if(!a) return z;
62 #define ARG_CHECK2(a, b, z) if(!a || !b) return z;
63 #define ARG_CHECK3(a, b, c, z) if(!a || !b || !c) return z;
64 
65 #elif defined(DEBUG)
66 
67 #define ARG_CHECK1(a, z) assert(a);
68 #define ARG_CHECK2(a, b, z) assert(a); assert(b);
69 #define ARG_CHECK3(a, b, c, z) assert(a); assert(b); assert(c);
70 
71 #else
72 
73 #define ARG_CHECK1(a, z)
74 #define ARG_CHECK2(a, b, z)
75 #define ARG_CHECK3(a, b, c, z)
76 
77 #endif
78 
79 typedef struct _ip {
80     int family;
81     int bits;
82 
83     /* see sfip_size(): these address bytes
84      * must be the last field in this struct */
85     union
86     {
87         u_int8_t  u6_addr8[16];
88         u_int16_t u6_addr16[8];
89         u_int32_t u6_addr32[4];
90 //        u_int64_t    u6_addr64[2];
91     } ip;
92     #define ip8  ip.u6_addr8
93     #define ip16 ip.u6_addr16
94     #define ip32 ip.u6_addr32
95 //    #define ip64 ip.u6_addr64
96 } sfip_t;
97 
98 typedef enum _return_values {
99     SFIP_SUCCESS=0,
100     SFIP_FAILURE,
101     SFIP_LESSER,
102     SFIP_GREATER,
103     SFIP_EQUAL,
104     SFIP_ARG_ERR,
105     SFIP_CIDR_ERR,
106     SFIP_INET_PARSE_ERR,
107     SFIP_INVALID_MASK,
108     SFIP_ALLOC_ERR,
109     SFIP_CONTAINS,
110     SFIP_NOT_CONTAINS,
111     SFIP_DUPLICATE,         /* Tried to add a duplicate variable name to table */
112     SFIP_LOOKUP_FAILURE,    /* Failed to lookup a variable from the table */
113     SFIP_UNMATCHED_BRACKET, /* IP lists that are missing a closing bracket */
114     SFIP_NOT_ANY,           /* For !any */
115     SFIP_CONFLICT           /* For IP conflicts in IP lists */
116 } SFIP_RET;
117 
118 
119 /* IP allocations and setting ******************************************/
120 
121 /* Parses "src" and stores results in "dst" */
122 /* If the conversion is invalid, returns SFIP_FAILURE */
123 SFIP_RET sfip_pton(const char *src, sfip_t *dst);
124 
125 /* Allocate IP address from a character array describing the IP */
126 sfip_t *sfip_alloc(const char *ip, SFIP_RET *status);
127 
128 /* Frees an sfip_t */
129 void sfip_free(sfip_t *ip);
130 
131 /* Allocate IP address from an array of integers.  The array better be
132  * long enough for the given family! */
133 sfip_t *sfip_alloc_raw(void *ip, int family, SFIP_RET *status);
134 
135 /* Sets existing IP, "dst", to a raw source IP (4 or 16 bytes,
136  * according to family) */
137 SFIP_RET sfip_set_raw(sfip_t *dst, void *src, int src_family);
138 
139 /* Sets existing IP, "dst", to be source IP, "src" */
140 SFIP_RET sfip_set_ip(sfip_t *dst, sfip_t *src);
141 
142 /* Obfuscates an IP */
143 void sfip_obfuscate(sfip_t *ob, sfip_t *ip);
144 
145 /* return required size (eg for hashing)
146  * requires that address bytes be the last field in sfip_t */
sfip_size(sfip_t * ipt)147 static INLINE unsigned int sfip_size(sfip_t* ipt)
148 {
149     if ( ipt->family == AF_INET6 ) return sizeof(*ipt);
150     return (unsigned int)((ipt->ip.u6_addr8+4) - (u_int8_t*)ipt);
151 }
152 
153 /* Member-access *******************************************************/
154 
155 /* Returns the family of "ip", either AF_INET or AF_INET6 */
156 /* XXX This is a performance critical function,
157 *  need to determine if it's safe to not check these pointers */
158 // ARG_CHECK1(ip, 0);
159 #define sfip_family(ip) ip->family
160 
161 /* Returns the number of bits used for masking "ip" */
sfip_bits(sfip_t * ip)162 static INLINE unsigned char sfip_bits(sfip_t *ip) {
163     ARG_CHECK1(ip, 0);
164     return (unsigned char)ip->bits;
165 }
166 
sfip_set_bits(sfip_t * p,int bits)167 static INLINE void sfip_set_bits(sfip_t *p, int bits) {
168 
169     if(!p)
170         return;
171 
172     if(bits < 0 || bits > 128) return;
173 
174     p->bits = bits;
175 }
176 
177 /* Returns the raw IP address as an in6_addr */
178 //inline struct in6_addr sfip_to_raw(sfip_t *);
179 
180 
181 
182 /* IP Comparisons ******************************************************/
183 
184 /* Check if ip is contained within the network specified by net */
185 /* Returns SFIP_EQUAL if so */
186 SFIP_RET sfip_contains(sfip_t *net, sfip_t *ip);
187 
188 /* Returns 1 if the IP is non-zero. 0 otherwise */
189 /* XXX This is a performance critical function, \
190  *  need to determine if it's safe to not check these pointers */\
sfip_is_set(sfip_t * ip)191 static INLINE int sfip_is_set(sfip_t *ip) {
192 //    ARG_CHECK1(ip, -1);
193     return ip->ip32[0] ||
194             ( (ip->family == AF_INET6) &&
195               (ip->ip32[1] ||
196               ip->ip32[2] ||
197               ip->ip32[3] || ip->bits != 128)) || ((ip->family == AF_INET) && ip->bits != 32)  ;
198 }
199 
200 /* Return 1 if the IP is a loopback IP */
201 int sfip_is_loopback(sfip_t *ip);
202 
203 /* Returns 1 if the IPv6 address appears mapped. 0 otherwise. */
204 int sfip_ismapped(sfip_t *ip);
205 
206 /* Support function for sfip_compare */
_ip4_cmp(u_int32_t ip1,u_int32_t ip2)207 static INLINE int _ip4_cmp(u_int32_t ip1, u_int32_t ip2) {
208     u_int32_t hip1 = htonl(ip1);
209     u_int32_t hip2 = htonl(ip2);
210     if(hip1 < hip2) return SFIP_LESSER;
211     if(hip1 > hip2) return SFIP_GREATER;
212     return SFIP_EQUAL;
213 }
214 
215 /* Support function for sfip_compare */
_ip6_cmp(sfip_t * ip1,sfip_t * ip2)216 static INLINE int _ip6_cmp(sfip_t *ip1, sfip_t *ip2) {
217     SFIP_RET ret;
218     u_int32_t *p1, *p2;
219 
220     /* XXX
221      * Argument are assumed trusted!
222      * This function is presently only called by sfip_compare
223      * on validated pointers.
224      * XXX */
225 
226     p1 = ip1->ip32;
227     p2 = ip2->ip32;
228 
229     if( (ret = _ip4_cmp(p1[0], p2[0])) != SFIP_EQUAL) return ret;
230     if( (ret = _ip4_cmp(p1[1], p2[1])) != SFIP_EQUAL) return ret;
231     if( (ret = _ip4_cmp(p1[2], p2[2])) != SFIP_EQUAL) return ret;
232     if( (ret = _ip4_cmp(p1[3], p2[3])) != SFIP_EQUAL) return ret;
233 
234     return ret;
235 }
236 
237 /* Compares two IPs
238  * Returns SFIP_LESSER, SFIP_EQUAL, SFIP_GREATER, if ip1 is less than, equal to,
239  * or greater than ip2 In the case of mismatched families, the IPv4 address
240  * is converted to an IPv6 representation. */
241 /* XXX-IPv6 Should add version of sfip_compare that just tests equality */
sfip_compare(sfip_t * ip1,sfip_t * ip2)242 static INLINE SFIP_RET sfip_compare(sfip_t *ip1, sfip_t *ip2) {
243     int f1,f2;
244 
245     ARG_CHECK2(ip1, ip2, SFIP_ARG_ERR);
246 
247     /* This is being done because at some points in the existing Snort code,
248      * an unset IP is considered to match anything.  Thus, if either IP is not
249      * set here, it's considered equal. */
250     if(!sfip_is_set(ip1) || !sfip_is_set(ip2)) return SFIP_EQUAL;
251 
252     f1 = sfip_family(ip1);
253     f2 = sfip_family(ip2);
254 
255     if(f1 == AF_INET && f2 == AF_INET) {
256         return _ip4_cmp(*ip1->ip32, *ip2->ip32);
257     }
258 /* Mixed families not presently supported */
259 #if 0
260     else if(f1 == AF_INET && f2 == AF_INET6) {
261         conv = sfip_4to6(ip1);
262         return _ip6_cmp(&conv, ip2);
263     } else if(f1 == AF_INET6 && f2 == AF_INET) {
264         conv = sfip_4to6(ip2);
265         return _ip6_cmp(ip1, &conv);
266     }
267     else {
268         return _ip6_cmp(ip1, ip2);
269     }
270 #endif
271     else if(f1 == AF_INET6 && f2 == AF_INET6) {
272         return _ip6_cmp(ip1, ip2);
273     }
274 
275     return SFIP_FAILURE;
276 }
277 
278 /* Compares two IPs
279  * Returns SFIP_LESSER, SFIP_EQUAL, SFIP_GREATER, if ip1 is less than, equal to,
280  * or greater than ip2 In the case of mismatched families, the IPv4 address
281  * is converted to an IPv6 representation. */
282 /* XXX-IPv6 Should add version of sfip_compare that just tests equality */
sfip_compare_unset(sfip_t * ip1,sfip_t * ip2)283 static INLINE SFIP_RET sfip_compare_unset(sfip_t *ip1, sfip_t *ip2) {
284     int f1,f2;
285 
286     ARG_CHECK2(ip1, ip2, SFIP_ARG_ERR);
287 
288     /* This is to handle the special case when one of the values being
289      * unset is considered to match nothing.  This is the opposite of
290      * sfip_compare(), defined above.  Thus, if either IP is not
291      * set here, it's considered not equal. */
292     if(!sfip_is_set(ip1) || !sfip_is_set(ip2)) return SFIP_FAILURE;
293 
294     f1 = sfip_family(ip1);
295     f2 = sfip_family(ip2);
296 
297     if(f1 == AF_INET && f2 == AF_INET) {
298         return _ip4_cmp(*ip1->ip32, *ip2->ip32);
299     }
300 /* Mixed families not presently supported */
301 #if 0
302     else if(f1 == AF_INET && f2 == AF_INET6) {
303         conv = sfip_4to6(ip1);
304         return _ip6_cmp(&conv, ip2);
305     } else if(f1 == AF_INET6 && f2 == AF_INET) {
306         conv = sfip_4to6(ip2);
307         return _ip6_cmp(ip1, &conv);
308     }
309     else {
310         return _ip6_cmp(ip1, ip2);
311     }
312 #endif
313     else if(f1 == AF_INET6 && f2 == AF_INET6) {
314         return _ip6_cmp(ip1, ip2);
315     }
316 
317     return SFIP_FAILURE;
318 }
319 
sfip_fast_lt4(sfip_t * ip1,sfip_t * ip2)320 static INLINE int sfip_fast_lt4(sfip_t *ip1, sfip_t *ip2) {
321     return *ip1->ip32 < *ip2->ip32;
322 }
sfip_fast_gt4(sfip_t * ip1,sfip_t * ip2)323 static INLINE int sfip_fast_gt4(sfip_t *ip1, sfip_t *ip2) {
324     return *ip1->ip32 > *ip2->ip32;
325 }
sfip_fast_eq4(sfip_t * ip1,sfip_t * ip2)326 static INLINE int sfip_fast_eq4(sfip_t *ip1, sfip_t *ip2) {
327     return *ip1->ip32 == *ip2->ip32;
328 }
329 
sfip_fast_lt6(sfip_t * ip1,sfip_t * ip2)330 static INLINE int sfip_fast_lt6(sfip_t *ip1, sfip_t *ip2) {
331     u_int32_t *p1, *p2;
332 
333     p1 = ip1->ip32;
334     p2 = ip2->ip32;
335 
336     if(*p1 < *p2) return 1;
337     else if(*p1 > *p2) return 0;
338 
339     if(p1[1] < p2[1]) return 1;
340     else if(p1[1] > p2[1]) return 0;
341 
342     if(p1[2] < p2[2]) return 1;
343     else if(p1[2] > p2[2]) return 0;
344 
345     if(p1[3] < p2[3]) return 1;
346     else if(p1[3] > p2[3]) return 0;
347 
348     return 0;
349 }
350 
sfip_fast_gt6(sfip_t * ip1,sfip_t * ip2)351 static INLINE int sfip_fast_gt6(sfip_t *ip1, sfip_t *ip2) {
352     u_int32_t *p1, *p2;
353 
354     p1 = ip1->ip32;
355     p2 = ip2->ip32;
356 
357     if(*p1 > *p2) return 1;
358     else if(*p1 < *p2) return 0;
359 
360     if(p1[1] > p2[1]) return 1;
361     else if(p1[1] < p2[1]) return 0;
362 
363     if(p1[2] > p2[2]) return 1;
364     else if(p1[2] < p2[2]) return 0;
365 
366     if(p1[3] > p2[3]) return 1;
367     else if(p1[3] < p2[3]) return 0;
368 
369     return 0;
370 }
371 
sfip_fast_eq6(sfip_t * ip1,sfip_t * ip2)372 static INLINE int sfip_fast_eq6(sfip_t *ip1, sfip_t *ip2) {
373     u_int32_t *p1, *p2;
374 
375     p1 = ip1->ip32;
376     p2 = ip2->ip32;
377 
378     if(*p1 != *p2) return 0;
379     if(p1[1] != p2[1]) return 0;
380     if(p1[2] != p2[2]) return 0;
381     if(p1[3] != p2[3]) return 0;
382 
383     return 1;
384 }
385 
386 /* Checks if ip2 is equal to ip1 or contained within the CIDR ip1 */
sfip_fast_cont4(sfip_t * ip1,sfip_t * ip2)387 static INLINE int sfip_fast_cont4(sfip_t *ip1, sfip_t *ip2) {
388     u_int32_t shift = 32 - sfip_bits(ip1);
389     u_int32_t ip = ntohl(*ip2->ip32);
390 
391     ip >>= shift;
392     ip <<= shift;
393 
394     return ntohl(*ip1->ip32) == ip;
395 }
396 
397 /* Checks if ip2 is equal to ip1 or contained within the CIDR ip1 */
sfip_fast_cont6(sfip_t * ip1,sfip_t * ip2)398 static INLINE int sfip_fast_cont6(sfip_t *ip1, sfip_t *ip2) {
399     u_int32_t ip;
400     int i, bits = sfip_bits(ip1);
401     int words = bits / 32;
402     bits = 32 - (bits % 32);
403 
404     for ( i = 0; i < words; i++ ) {
405         if ( ip1->ip32[i] != ip2->ip32[i] )
406             return 0;
407     }
408 
409     if ( bits == 32 ) return 1;
410 
411     ip = ntohl(ip2->ip32[i]);
412 
413     ip >>= bits;
414     ip <<= bits;
415 
416     return ntohl(ip1->ip32[i]) == ip;
417 }
418 
419 #define sfip_equals(x,y) (sfip_compare(&x, &y) == SFIP_EQUAL)
420 #define sfip_not_equals !sfip_equals
421 #define sfip_clear(x) memset(x, 0, 16)
422 
423 /* Printing ************************************************************/
424 
425 /* Uses a static buffer to return a string representation of the IP */
426 char *sfip_to_str(const sfip_t *ip);
427 #define sfip_ntoa(x) sfip_to_str(x)
428 void sfip_raw_ntop(int family, const void *ip_raw, char *buf, int bufsize);
429 
430 #endif // SF_IP_H
431 
432