1 /*
2 * Copyright (C) 2004-2010 Christos Tsantilas
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 * MA 02110-1301 USA.
18 */
19
20 #include "common.h"
21 #include "c-icap.h"
22 #include "net_io.h"
23 #include "mem.h"
24 #include "lookup_table.h"
25 #include "cfg_param.h"
26 #include "filetype.h"
27 #include "debug.h"
28 #if defined(USE_REGEX)
29 #include "ci_regex.h"
30 #endif
31
32 /*string operators */
stringdup(const char * str,ci_mem_allocator_t * allocator)33 void *stringdup(const char *str, ci_mem_allocator_t *allocator)
34 {
35 char *new_s = allocator->alloc(allocator,strlen(str)+1);
36 if (new_s)
37 strcpy(new_s, str);
38 return new_s;
39 }
40
stringcmp(const void * key1,const void * key2)41 int stringcmp(const void *key1,const void *key2)
42 {
43 if (!key2)
44 return -1;
45 return strcmp((const char *)key1,(const char *)key2);
46 }
47
stringequal(const void * key1,const void * key2)48 int stringequal(const void *key1,const void *key2)
49 {
50 if (!key2)
51 return 0;
52 return strcmp((const char *)key1,(const char *)key2) == 0;
53 }
54
stringlen(const void * key)55 size_t stringlen(const void *key)
56 {
57 return strlen((const char *)key)+1;
58 }
59
stringfree(void * key,ci_mem_allocator_t * allocator)60 void stringfree(void *key, ci_mem_allocator_t *allocator)
61 {
62 allocator->free(allocator, key);
63 }
64
65 const ci_type_ops_t ci_str_ops = {
66 stringdup,
67 stringfree,
68 stringcmp,
69 stringlen,
70 stringequal,
71 };
72
string_ext_cmp(const void * key1,const void * key2)73 int string_ext_cmp(const void *key1,const void *key2)
74 {
75 if (!key2)
76 return -1;
77
78 if (strcmp((const char *)key1, "*") == 0)
79 return 0;
80
81 return strcmp((const char *)key1,(const char *)key2);
82 }
83
string_ext_equal(const void * key1,const void * key2)84 int string_ext_equal(const void *key1,const void *key2)
85 {
86 if (!key2)
87 return 0;
88
89 if (strcmp((const char *)key1, "*") == 0)
90 return 1;
91
92 return strcmp((const char *)key1,(const char *)key2) == 0;
93 }
94
95
96 const ci_type_ops_t ci_str_ext_ops = {
97 stringdup,
98 stringfree,
99 string_ext_cmp,
100 stringlen,
101 string_ext_equal,
102 };
103
104
105 /*int32 operators*/
106
int32_dup(const char * str,ci_mem_allocator_t * allocator)107 void *int32_dup(const char *str, ci_mem_allocator_t *allocator)
108 {
109 int32_t *i;
110 char *e = NULL;
111 i = allocator->alloc(allocator, sizeof(int32_t));
112 if (i) {
113 *i = strtol(str, &e, 10);
114 if (*e == 'K' || *e == 'k')
115 *i = *i * 1000;
116 else if (*e == 'M' || *e == 'm')
117 *i = *i * 1000000;
118 else if (*e == 'G' || *e == 'g')
119 *i = *i * 1000000000;
120 }
121 return (void *)i;
122
123 }
124
int32_cmp(const void * key1,const void * key2)125 int int32_cmp(const void *key1,const void *key2)
126 {
127 int32_t k1, k2;
128 k1 = *(int32_t *)key1;
129 k2 = *(int32_t *)key2;
130 if (k1 < k2)
131 return -1;
132 if (k1 > k2)
133 return 1;
134
135 return 0;
136 }
137
int32_equal(const void * key1,const void * key2)138 int int32_equal(const void *key1,const void *key2)
139 {
140 int32_t k1,k2;
141 k1 = *(int32_t *)key1;
142 k2 = *(int32_t *)key2;
143 return k1 == k2;
144 }
145
int32_len(const void * key)146 size_t int32_len(const void *key)
147 {
148 return (size_t)4;
149 }
150
int32_free(void * key,ci_mem_allocator_t * allocator)151 void int32_free(void *key, ci_mem_allocator_t *allocator)
152 {
153 /*nothing*/
154 allocator->free(allocator, key);
155 }
156
157 const ci_type_ops_t ci_int32_ops = {
158 int32_dup,
159 int32_free,
160 int32_cmp,
161 int32_len,
162 int32_equal
163 };
164
165 /*uint64 operators*/
uint64_dup(const char * str,ci_mem_allocator_t * allocator)166 void *uint64_dup(const char *str, ci_mem_allocator_t *allocator)
167 {
168 uint64_t *i;
169 char *e = NULL;
170 i = allocator->alloc(allocator, sizeof(uint64_t));
171 if (i) {
172 *i = strtoll(str, &e, 10);
173 if (*e == 'K' || *e == 'k')
174 *i = *i * 1000;
175 else if (*e == 'M' || *e == 'm')
176 *i = *i * 1000000;
177 else if (*e == 'G' || *e == 'g')
178 *i = *i * 1000000000;
179 }
180 return (void *)i;
181 }
182
uint64_cmp(const void * key1,const void * key2)183 int uint64_cmp(const void *key1,const void *key2)
184 {
185 uint64_t k1,k2;
186 k1 = *(uint64_t *)key1;
187 k2 = *(uint64_t *)key2;
188 if (k1 < k2)
189 return -1;
190 if (k1 > k2)
191 return 1;
192
193 return 0;
194 }
195
uint64_equal(const void * key1,const void * key2)196 int uint64_equal(const void *key1,const void *key2)
197 {
198 uint64_t k1,k2;
199 k1 = *(uint64_t *)key1;
200 k2 = *(uint64_t *)key2;
201 return k1 == k2;
202 }
203
uint64_free(void * key,ci_mem_allocator_t * allocator)204 void uint64_free(void *key, ci_mem_allocator_t *allocator)
205 {
206 allocator->free(allocator, key);
207 }
208
uint64_len(const void * key)209 size_t uint64_len(const void *key)
210 {
211 return (size_t)sizeof(uint64_t);
212 }
213
214 const ci_type_ops_t ci_uint64_ops = {
215 uint64_dup,
216 uint64_free,
217 uint64_cmp,
218 uint64_len,
219 uint64_equal
220 };
221
222
223 /*regular expresion operator definition */
224 #if defined(USE_REGEX)
225 /*We only need the preg field which holds the compiled regular expression
226 but keep the uncompiled string too just for debuging reasons */
227 struct ci_acl_regex {
228 char *str;
229 int flags;
230 ci_regex_t preg;
231 };
232
233 /*Parse the a regular expression in the form: /regexpression/flags
234 where flags nothing or 'i'. Examples:
235 /^\{[a-z| ]*\}/i
236 /^some test.*t/
237 */
regex_dup(const char * str,ci_mem_allocator_t * allocator)238 void *regex_dup(const char *str, ci_mem_allocator_t *allocator)
239 {
240 struct ci_acl_regex *reg;
241 char *newstr;
242 int flags, recursive;
243
244 newstr = ci_regex_parse(str, &flags, &recursive);
245
246 if (!newstr) {
247 ci_debug_printf(1,"Parse error, while parsing regex: '%s')!\n", str);
248 return NULL;
249 }
250
251 reg = allocator->alloc(allocator,sizeof(struct ci_acl_regex));
252 if (!reg) {
253 ci_debug_printf(1,"Error allocating memory for regex_dup (1)!\n");
254 free(newstr);
255 return NULL;
256 }
257
258 if ((reg->preg = ci_regex_build(newstr, flags)) == NULL) {
259 ci_debug_printf(1, "Error compiling regular expression :%s (%s)\n", str, newstr);
260 allocator->free(allocator, reg);
261 free(newstr);
262 return NULL;
263 }
264
265 reg->str = newstr;
266 reg->flags = flags;
267
268 return reg;
269 }
270
regex_cmp(const void * key1,const void * key2)271 int regex_cmp(const void *key1, const void *key2)
272 {
273 struct ci_acl_regex *reg = (struct ci_acl_regex *)key1;
274 if (!key2)
275 return -1;
276 return (ci_regex_apply(reg->preg, (const char *)key2, strlen(key2), 0, NULL, NULL) == 0 ? 1 : 0);
277 }
278
regex_equal(const void * key1,const void * key2)279 int regex_equal(const void *key1, const void *key2)
280 {
281 struct ci_acl_regex *reg = (struct ci_acl_regex *)key1;
282 if (!key2)
283 return 0;
284 return ci_regex_apply(reg->preg, (const char *)key2, strlen(key2), 0, NULL, NULL) != 0;
285 }
286
regex_len(const void * key)287 size_t regex_len(const void *key)
288 {
289 return strlen(((const struct ci_acl_regex *)key)->str);
290 }
291
regex_free(void * key,ci_mem_allocator_t * allocator)292 void regex_free(void *key, ci_mem_allocator_t *allocator)
293 {
294 struct ci_acl_regex *reg = (struct ci_acl_regex *)key;
295 ci_regex_free(reg->preg);
296 allocator->free(allocator, reg->str);
297 allocator->free(allocator, reg);
298 }
299
300
301 const ci_type_ops_t ci_regex_ops = {
302 regex_dup,
303 regex_free,
304 regex_cmp,
305 regex_len,
306 regex_equal
307 };
308 #endif
309
310 /*filetype operators*/
datatype_dup(const char * str,ci_mem_allocator_t * allocator)311 void *datatype_dup(const char *str, ci_mem_allocator_t *allocator)
312 {
313 int type;
314 unsigned int *val = allocator->alloc(allocator,sizeof(unsigned int));
315 if ((type = ci_magic_type_id(str)) >= 0) {
316 *val = type;
317 } else if ( (type = ci_magic_group_id(str)) >= 0) {
318 *val = type;
319 *val = *val << 16;
320 } else {
321 allocator->free(allocator, val);
322 val = NULL;
323 }
324
325 return (void *)val;
326 }
327
datatype_cmp(const void * key1,const void * key2)328 int datatype_cmp(const void *key1, const void *key2)
329 {
330 unsigned int type = *(unsigned int *)key1;
331
332 if (!key2)
333 return -1;
334
335 if ( (0xFFFF0000 & type) == 0)
336 return (*(unsigned int *)key1 - *(unsigned int *)key2);
337 else { /*type is group check if key2 belongs to group*/
338 type = type >> 16;
339 if (ci_magic_group_check(*(unsigned int *)key2, type))
340 return 0;
341 else
342 return 1;
343 }
344 }
345
datatype_equal(const void * key1,const void * key2)346 int datatype_equal(const void *key1, const void *key2)
347 {
348 unsigned int type = *(unsigned int *)key1;
349
350 if (!key2)
351 return 0;
352
353 if ( (0xFFFF0000 & type) == 0)
354 return *(unsigned int *)key1 == *(unsigned int *)key2;
355 else { /*type is group check if key2 belongs to group*/
356 type = type >> 16;
357 if (ci_magic_group_check(*(unsigned int *)key2, (int)type))
358 return 1;
359 else
360 return 0;
361 }
362 }
363
datatype_len(const void * key)364 size_t datatype_len(const void *key)
365 {
366 return sizeof(unsigned int);
367 }
368
datatype_free(void * key,ci_mem_allocator_t * allocator)369 void datatype_free(void *key, ci_mem_allocator_t *allocator)
370 {
371 /*nothing*/
372 allocator->free(allocator, key);
373 }
374
375 const ci_type_ops_t ci_datatype_ops = {
376 datatype_dup,
377 datatype_free,
378 datatype_cmp,
379 datatype_len,
380 datatype_equal
381 };
382
383 /*IP operators*/
384 #ifdef HAVE_IPV6
385
386 void ci_list_ipv4_to_ipv6();
387
388 #define ci_ipv4_inaddr_is_zero(addr) ((addr).ipv4_addr.s_addr==0)
389 #define ci_ipv4_inaddr_are_equal(addr1,addr2) ((addr1).ipv4_addr.s_addr == (addr2).ipv4_addr.s_addr)
390 #define ci_ipv4_inaddr_zero(addr) ((addr).ipv4_addr.s_addr=0)
391
392 #define ci_ipv6_inaddr_is_zero(addr) ( ci_in6_addr_u32(addr)[0] == 0 && \
393 ci_in6_addr_u32(addr)[1] == 0 && \
394 ci_in6_addr_u32(addr)[2] == 0 && \
395 ci_in6_addr_u32(addr)[3] == 0)
396
397 #define ci_ipv6_inaddr_are_equal(addr1,addr2) ( ci_in6_addr_u32(addr1)[0] == ci_in6_addr_u32(addr2)[0] && \
398 ci_in6_addr_u32(addr1)[1] == ci_in6_addr_u32(addr2)[1] && \
399 ci_in6_addr_u32(addr1)[2] == ci_in6_addr_u32(addr2)[2] && \
400 ci_in6_addr_u32(addr1)[3] == ci_in6_addr_u32(addr2)[3])
401
402
403 #define ci_ipv6_inaddr_is_v4mapped(addr) (ci_in6_addr_u32(addr)[0] == 0 &&\
404 ci_in6_addr_u32(addr)[1] == 0 && \
405 ci_in6_addr_u32(addr)[2] == htonl(0xFFFF))
406
407
408 #define ci_ipv4_inaddr_check_net(addr1,addr2,mask) (((addr1).ipv4_addr.s_addr & (mask).ipv4_addr.s_addr) == ((addr2).ipv4_addr.s_addr & (mask).ipv4_addr.s_addr))
409 #define ci_ipv6_inaddr_check_net(addr1,addr2,mask) ((ci_in6_addr_u32(addr1)[0] & ci_in6_addr_u32(mask)[0]) == (ci_in6_addr_u32(addr2)[0] & ci_in6_addr_u32(mask)[0]) &&\
410 (ci_in6_addr_u32(addr1)[1] & ci_in6_addr_u32(mask)[1]) == (ci_in6_addr_u32(addr2)[1] & ci_in6_addr_u32(mask)[1]) && \
411 (ci_in6_addr_u32(addr1)[2] & ci_in6_addr_u32(mask)[2]) == (ci_in6_addr_u32(addr2)[2] & ci_in6_addr_u32(mask)[2]) && \
412 (ci_in6_addr_u32(addr1)[3] & ci_in6_addr_u32(mask)[3]) == (ci_in6_addr_u32(addr2)[3] & ci_in6_addr_u32(mask)[3]))
413 #define ci_ipv4_in_ipv6_check_net(addr1, addr2, mask) (ci_in6_addr_u32(addr2)[0] == 0 && \
414 ci_in6_addr_u32(addr2)[1] == 0 && \
415 ci_in6_addr_u32(addr2)[2] == htonl(0xFFFF) && \
416 ((addr1).ipv4_addr.s_addr & (mask).ipv4_addr.s_addr) == (ci_in6_addr_u32(addr2)[3] & (mask).ipv4_addr.s_addr))
417 #define ci_ipv6_in_ipv4_check_net(addr1, addr2, mask) (ci_in6_addr_u32(addr1)[0] == 0 && \
418 ci_in6_addr_u32(addr1)[1] == 0 && \
419 ci_in6_addr_u32(addr1)[2] == htonl(0xFFFF) && \
420 (ci_in6_addr_u32(addr1)[3] & (mask).ipv4_addr.s_addr) == ((addr2).ipv4_addr.s_addr & (mask).ipv4_addr.s_addr))
421
422
423 /*We can do this because ipv4_addr in practice exists in s6_addr[0]*/
424 #define ci_inaddr_ipv4_to_ipv6(addr)( ci_in6_addr_u32(addr)[3] = (addr).ipv4_addr.s_addr,\
425 ci_in6_addr_u32(addr)[0] = 0, \
426 ci_in6_addr_u32(addr)[1] = 0, \
427 ci_in6_addr_u32(addr)[2] = htonl(0xFFFF))
428 #define ci_netmask_ipv4_to_ipv6(addr)(ci_in6_addr_u32(addr)[3] = (addr).ipv4_addr.s_addr, \
429 ci_in6_addr_u32(addr)[0] = htonl(0xFFFFFFFF), \
430 ci_in6_addr_u32(addr)[1] = htonl(0xFFFFFFFF), \
431 ci_in6_addr_u32(addr)[2] = htonl(0xFFFFFFFF))
432 #else /*if no HAVE_IPV6 */
433
434 #define ci_ipv4_inaddr_is_zero(addr) ((addr).s_addr==0)
435 #define ci_ipv4_inaddr_are_equal(addr1,addr2) ((addr1).s_addr == (addr2).s_addr)
436 #define ci_ipv4_inaddr_check_net(addr1,addr2,mask) (((addr1).s_addr & (mask).s_addr) == ((addr2).s_addr & (mask).s_addr))
437
438 #define ci_ipv4_inaddr_zero(addr) ((addr).s_addr=0)
439
440 #endif /*ifdef HAVE_IPV6 */
441
442
443
444
ip_dup(const char * value,ci_mem_allocator_t * allocator)445 void *ip_dup(const char *value, ci_mem_allocator_t *allocator)
446 {
447 int socket_family, len;
448 ci_ip_t *ip;
449 char str_addr[CI_IPLEN+1], str_netmask[CI_IPLEN+1];
450 char *pstr;
451 ci_in_addr_t address, netmask;
452
453 ci_inaddr_zero(address);
454 ci_inaddr_zero(netmask);
455
456 #ifdef HAVE_IPV6
457 if (strchr(value,':'))
458 socket_family = AF_INET6;
459 else
460 #endif
461 socket_family = AF_INET;
462
463 if ((pstr=strchr(value,'/'))) {
464 len=(pstr-value);
465 if (len >= CI_IPLEN) {
466 ci_debug_printf(1,"Invalid ip address (len>%d): %s\n", CI_IPLEN, value);
467 return NULL;
468 }
469 strncpy(str_addr,value,len);
470 str_addr[len] = '\0';
471
472 if (!ci_inet_aton(socket_family, str_addr, &address)) {
473 ci_debug_printf(1,"Invalid ip address in network %s definition\n", value);
474 return NULL;
475 }
476
477 strncpy(str_netmask, pstr+1, CI_IPLEN);
478 str_netmask[CI_IPLEN] = '\0';
479
480 if (!ci_inet_aton(socket_family, str_netmask, &netmask)) {
481 ci_debug_printf(1,"Invalid netmask in network %s definition\n", value);
482 return NULL;
483 }
484 } else { /*No netmask defined is a host ip*/
485 if (!ci_inet_aton(socket_family, value, &address)) {
486 ci_debug_printf(1,"Invalid ip address: %s\n", value);
487 return NULL;
488 }
489 #ifdef HAVE_IPV6
490 if (socket_family==AF_INET)
491 ci_ipv4_inaddr_hostnetmask(netmask);
492 else
493 ci_ipv6_inaddr_hostnetmask(netmask);
494 #else
495 ci_ipv4_inaddr_hostnetmask(netmask);
496 #endif
497 }
498
499 ip= allocator->alloc(allocator, sizeof(ci_ip_t));
500 ip->family = socket_family;
501
502 ci_inaddr_copy(ip->address, address);
503 ci_inaddr_copy(ip->netmask, netmask);
504
505 return ip;
506 }
507
ip_free(void * data,ci_mem_allocator_t * allocator)508 void ip_free(void *data, ci_mem_allocator_t *allocator)
509 {
510 allocator->free(allocator, data);
511 }
512
ip_len(const void * key)513 size_t ip_len(const void *key)
514 {
515 return sizeof(ci_ip_t);
516 }
517
ip_cmp(const void * ref_key,const void * key_check)518 int ip_cmp(const void *ref_key, const void *key_check)
519 {
520 /*Not implemented*/
521 return 0;
522 }
523
ip_equal(const void * ref_key,const void * key_check)524 int ip_equal(const void *ref_key, const void *key_check)
525 {
526 const ci_ip_t *ip_ref = (const ci_ip_t *)ref_key;
527 const ci_ip_t *ip_check = (const ci_ip_t *)key_check;
528 char buf[128],buf1[128],buf2[128];
529
530 if (!ip_check)
531 return 0;
532
533 ci_debug_printf(9,"going to check addresses ip address: %s %s/%s\n",
534 ci_inet_ntoa(ip_check->family,&ip_check->address, buf, 128),
535 ci_inet_ntoa(ip_ref->family,&ip_ref->address, buf1, 128),
536 ci_inet_ntoa(ip_ref->family,&ip_ref->netmask, buf2, 128)
537 );
538 #ifdef HAVE_IPV6
539 if (ip_check->family == AF_INET) {
540 if (ip_ref->family == AF_INET)
541 return ci_ipv4_inaddr_check_net(ip_ref->address, ip_check->address, ip_ref->netmask);
542 //else add->family == AF_INET6
543 return ci_ipv6_in_ipv4_check_net(ip_ref->address, ip_check->address, ip_ref->netmask);
544 }
545 //else assuming ip_check->family == AF_INET6
546 if (ip_ref->family == AF_INET6)
547 return ci_ipv6_inaddr_check_net(ip_ref->address, ip_check->address, ip_ref->netmask);
548 //else ip->family == AF_INET
549 return ci_ipv4_in_ipv6_check_net(ip_ref->address, ip_check->address, ip_ref->netmask);
550 #else
551 return ci_ipv4_inaddr_check_net(ip_ref->address, ip_check->address, ip_ref->netmask);
552 #endif
553
554 }
555
ip_sockaddr_cmp(const void * ref_key,const void * key_check)556 int ip_sockaddr_cmp(const void *ref_key, const void *key_check)
557 {
558 /*Not implemented*/
559 return 1;
560 }
561
ip_sockaddr_equal(const void * ref_key,const void * key_check)562 int ip_sockaddr_equal(const void *ref_key, const void *key_check)
563 {
564 const ci_ip_t *ip_ref = (const ci_ip_t *)ref_key;
565 const ci_sockaddr_t *ip_check = (const ci_sockaddr_t *)key_check;
566 char buf[128],buf1[128],buf2[128];
567
568 if (!ip_check)
569 return 0;
570
571 ci_debug_printf(9,"going to check addresses ip address: %s %s/%s\n",
572 ci_inet_ntoa(ip_check->ci_sin_family,ip_check->ci_sin_addr, buf, 128),
573 ci_inet_ntoa(ip_ref->family,&ip_ref->address, buf1, 128),
574 ci_inet_ntoa(ip_ref->family,&ip_ref->netmask, buf2, 128)
575 );
576 #ifdef HAVE_IPV6
577 if (ip_check->ci_sin_family == AF_INET) {
578 if (ip_ref->family == AF_INET)
579 return ci_ipv4_inaddr_check_net(ip_ref->address, *(ci_in_addr_t *)ip_check->ci_sin_addr, ip_ref->netmask);
580 //else add->family == AF_INET6
581 return ci_ipv6_in_ipv4_check_net(ip_ref->address, *(ci_in_addr_t *)ip_check->ci_sin_addr, ip_ref->netmask);
582 }
583 //else assuming ip_check->ci_sin_family == AF_INET6
584 if (ip_ref->family == AF_INET6)
585 return ci_ipv6_inaddr_check_net(ip_ref->address, *(ci_in_addr_t *)ip_check->ci_sin_addr, ip_ref->netmask);
586 //else ip->family == AF_INET
587 return ci_ipv4_in_ipv6_check_net(ip_ref->address, *(ci_in_addr_t *)ip_check->ci_sin_addr, ip_ref->netmask);
588 #else
589 return ci_ipv4_inaddr_check_net(ip_ref->address, *(ci_in_addr_t *)ip_check->ci_sin_addr, ip_ref->netmask);
590 #endif
591
592 }
593
594
595
596 const ci_type_ops_t ci_ip_ops = {
597 ip_dup,
598 ip_free,
599 ip_cmp,
600 ip_len,
601 ip_equal
602 };
603
604
605
606 const ci_type_ops_t ci_ip_sockaddr_ops = {
607 ip_dup,
608 ip_free,
609 ip_sockaddr_cmp,
610 ip_len,
611 ip_sockaddr_equal
612 };
613