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