What Eric and Zakir said

This commit is contained in:
Alex Halderman 2013-10-01 17:05:47 -04:00
parent dab1e823bd
commit bc3ec6456a
3 changed files with 93 additions and 9 deletions

View File

@ -125,5 +125,20 @@ int blacklist_init_from_files(char *whitelist_filename, char *blacklist_filename
uint64_t allowed = blacklist_count_allowed(); uint64_t allowed = blacklist_count_allowed();
log_debug("blacklist", "%lu addresses allowed to be scanned (%0.0f%% of address space)", log_debug("blacklist", "%lu addresses allowed to be scanned (%0.0f%% of address space)",
allowed, allowed*100./((long long int)1 << 32)); allowed, allowed*100./((long long int)1 << 32));
/*
// test
log_debug("blacklist", "testing started");
uint64_t count = constraint_count_ips(constraint, ADDR_ALLOWED);
for (unsigned int i=0; i < count; i++) {
int ip = constraint_lookup_index(constraint, i, ADDR_ALLOWED);
if ((i & 0xFFFFFF) == 0)
log_info("blacklist", "%x", i & 0xFF000000);
if (constraint_lookup_ip(constraint, ip) != ADDR_ALLOWED) {
log_error("blacklist", "test failed for index %d", i);
}
}
log_debug("blacklist", "testing complete");
*/
return 0; return 0;
} }

View File

@ -50,6 +50,7 @@ typedef struct node {
struct node *l; struct node *l;
struct node *r; struct node *r;
value_t value; value_t value;
uint64_t count;
} node_t; } node_t;
// As an optimization, we precompute lookups for every prefix of this // As an optimization, we precompute lookups for every prefix of this
@ -60,6 +61,8 @@ struct _constraint {
node_t *root; // root node of the tree node_t *root; // root node of the tree
node_t **radix; // array of nodes for every RADIX_LENGTH prefix node_t **radix; // array of nodes for every RADIX_LENGTH prefix
int optimized; // is radix populated and up-to-date? int optimized; // is radix populated and up-to-date?
int painted; // have we precomputed counts for each node?
value_t paint_value; // value for which we precomputed counts
}; };
// Tree operations respect the invariant that every node that isn't a // Tree operations respect the invariant that every node that isn't a
@ -176,7 +179,7 @@ static int _lookup_ip(node_t *root, uint32_t address)
// Return the value pertaining to an address. // Return the value pertaining to an address.
// (Note: address must be in host byte order.) // (Note: address must be in host byte order.)
int constraint_lookup_ip(constraint_t *con, uint32_t address) value_t constraint_lookup_ip(constraint_t *con, uint32_t address)
{ {
assert(con); assert(con);
if (con->optimized) { if (con->optimized) {
@ -193,27 +196,91 @@ int constraint_lookup_ip(constraint_t *con, uint32_t address)
} }
} }
// Return the nth painted IP address.
static int _lookup_index(node_t *root, uint64_t n)
{
assert(root);
node_t *node = root;
uint32_t ip = 0;
uint32_t mask = 0x80000000;
for (;;) {
if (IS_LEAF(node)) {
return ip | n;
}
if (n < node->l->count) {
node = node->l;
} else {
n -= node->l->count;
node = node->r;
ip |= mask;
}
mask >>= 1;
}
}
// For a given value, return the IP address with zero-based index n.
// (i.e., if there are three addresses with value 0xFF, looking up index 1
// will return the second one).
// Note that the tree must have been previously painted with this value.
uint32_t constraint_lookup_index(constraint_t *con, uint64_t index, value_t value)
{
assert(con);
if (!con->painted || con->paint_value != value) {
constraint_paint_value(con, value);
}
if (con->optimized) {
// TK TK TK
}
assert(index < con->root->count);
return _lookup_index(con->root, index);
}
// Implement count_ips by recursing on halves of the tree. Size represents // Implement count_ips by recursing on halves of the tree. Size represents
// the number of addresses in a prefix at the current level of the tree. // the number of addresses in a prefix at the current level of the tree.
static uint64_t _count_ips_recurse(node_t *node, value_t value, uint64_t size) // If paint is specified, each node will have its count set to the number of
// leaves under it set to value.
static uint64_t _count_ips_recurse(node_t *node, value_t value, uint64_t size, int paint)
{ {
assert(node); assert(node);
uint64_t n;
if (IS_LEAF(node)) { if (IS_LEAF(node)) {
if (node->value == value) { if (node->value == value) {
return size; n = size;
} else { } else {
return 0; n = 0;
} }
} else {
n = _count_ips_recurse(node->l, value, size >> 1, paint) +
_count_ips_recurse(node->r, value, size >> 1, paint);
} }
return _count_ips_recurse(node->l, value, size >> 1) + if (paint) {
_count_ips_recurse(node->r, value, size >> 1); node->count = n;
}
return n;
}
// For each node, precompute the count of leaves beneath it set to value.
// Note that the tree can be painted for only one value at a time.
void constraint_paint_value(constraint_t *con, value_t value)
{
assert(con);
log_info("constraint", "Painting value %lu", value);
_count_ips_recurse(con->root, value, (uint64_t)1 << 32, 1);
con->painted = 1;
con->paint_value = value;
} }
// Return the number of addresses that have a given value. // Return the number of addresses that have a given value.
uint64_t constraint_count_ips(constraint_t *con, value_t value) uint64_t constraint_count_ips(constraint_t *con, value_t value)
{ {
assert(con); assert(con);
return _count_ips_recurse(con->root, value, (uint64_t)1 << 32); if (con->painted && con->paint_value == value) {
return con->root->count;
} else {
return _count_ips_recurse(con->root, value, (uint64_t)1 << 32, 0);
}
} }
// Initialize the tree. // Initialize the tree.

View File

@ -2,13 +2,15 @@
#define _CONSTRAINT_H #define _CONSTRAINT_H
typedef struct _constraint constraint_t; typedef struct _constraint constraint_t;
typedef int value_t; typedef unsigned int value_t;
constraint_t* constraint_init(value_t value); constraint_t* constraint_init(value_t value);
void constraint_free(constraint_t *con); void constraint_free(constraint_t *con);
void constraint_set(constraint_t *con, uint32_t prefix, int len, value_t value); void constraint_set(constraint_t *con, uint32_t prefix, int len, value_t value);
void constraint_optimize(constraint_t *con); void constraint_optimize(constraint_t *con);
int constraint_lookup_ip(constraint_t *con, uint32_t address); value_t constraint_lookup_ip(constraint_t *con, uint32_t address);
uint64_t constraint_count_ips(constraint_t *con, value_t value); uint64_t constraint_count_ips(constraint_t *con, value_t value);
uint32_t constraint_lookup_index(constraint_t *con, uint64_t index, value_t value);
void constraint_paint_value(constraint_t *con, value_t value);
#endif //_CONSTRAINT_H #endif //_CONSTRAINT_H