};
struct rbldb_t {
- A(uint32_t) ips;
+ A(uint16_t) ips[1 << 16];
};
ARRAY(rbldb_t)
rbldb_t *db;
file_map_t map;
const char *p, *end;
+ uint32_t ips = 0;
if (!file_map_open(&map, file, false)) {
return NULL;
if (parse_ipv4(p, &p, &ip) < 0) {
p = (char *)memchr(p, '\n', end - p) + 1;
} else {
- array_add(db->ips, ip);
+ array_add(db->ips[ip >> 16], ip & 0xffff);
+ ++ips;
}
}
file_map_close(&map);
/* Lookup may perform serveral I/O, so avoid swap.
*/
- array_adjust(db->ips);
- if (lock && !array_lock(db->ips)) {
- UNIXERR("mlock");
- }
-
- if (db->ips.len) {
-# define QSORT_TYPE uint32_t
-# define QSORT_BASE db->ips.data
-# define QSORT_NELT db->ips.len
+ for (int i = 0 ; i < 1 << 16 ; ++i) {
+ array_adjust(db->ips[i]);
+ if (lock && !array_lock(db->ips[i])) {
+ UNIXERR("mlock");
+ }
+ if (db->ips[i].len) {
+# define QSORT_TYPE uint16_t
+# define QSORT_BASE db->ips[i].data
+# define QSORT_NELT db->ips[i].len
# define QSORT_LT(a,b) *a < *b
# include "qsort.c"
+ }
}
- info("rbl %s loaded, %d IPs", file, db->ips.len);
+ info("rbl %s loaded, %d IPs", file, ips);
return db;
}
static void rbldb_wipe(rbldb_t *db)
{
- array_wipe(db->ips);
+ for (int i = 0 ; i < 1 << 16 ; ++i) {
+ array_wipe(db->ips[i]);
+ }
}
void rbldb_delete(rbldb_t **db)
uint32_t rbldb_stats(const rbldb_t *rbl)
{
- return rbl->ips.len;
+ uint32_t ips = 0;
+ for (int i = 0 ; i < 1 << 16 ; ++i) {
+ ips += array_len(rbl->ips[i]);
+ }
+ return ips;
}
bool rbldb_ipv4_lookup(const rbldb_t *db, uint32_t ip)
{
- int l = 0, r = db->ips.len;
+ const uint16_t hip = ip >> 16;
+ const uint16_t lip = ip & 0xffff;
+ int l = 0, r = db->ips[hip].len;
while (l < r) {
int i = (r + l) / 2;
- if (array_elt(db->ips, i) == ip)
+ if (array_elt(db->ips[hip], i) == lip)
return true;
- if (ip < array_elt(db->ips, i)) {
+ if (lip < array_elt(db->ips[hip], i)) {
r = i;
} else {
l = i + 1;
* the file pointed by filename MUST be a valid ip list issued from
* the rsync (or equivalent) service of a (r)bl.
*/
- case ATK_FILE: {
+ case ATK_FILE: case ATK_RBLDNS: {
bool lock = false;
int weight = 0;
rbldb_t *rbl = NULL;
lock = false;
} else {
PARSE_CHECK(false, "illegal locking state %.*s",
- p - current, current);
+ (int)(p - current), current);
}
break;
weight = strtol(current, &next, 10);
PARSE_CHECK(next == p && weight >= 0 && weight <= 1024,
"illegal weight value %.*s",
- (p - current), current);
+ (int)(p - current), current);
break;
case 2:
}
} break;
- /* host parameter.
+ /* dns parameter.
* weight:hostname.
* define a RBL to use through DNS resolution.
*/
- case ATK_HOST: {
+ case ATK_DNS: {
int weight = 0;
const char *current = param->value;
const char *p = m_strchrnul(param->value, ':');
weight = strtol(current, &next, 10);
PARSE_CHECK(next == p && weight >= 0 && weight <= 1024,
"illegal weight value %.*s",
- (p - current), current);
+ (int)(p - current), current);
break;
case 1:
}
}}
- PARSE_CHECK(data->rbls.len,
+ PARSE_CHECK(data->rbls.len || data->host_offsets.len,
"no file parameter in the filter %s", filter->name);
filter->data = data;
return true;
/* Parameters.
*/
(void)filter_param_register(type, "file");
- (void)filter_param_register(type, "host");
+ (void)filter_param_register(type, "rbldns");
+ (void)filter_param_register(type, "dns");
(void)filter_param_register(type, "hard_threshold");
(void)filter_param_register(type, "soft_threshold");
return 0;