inital public release
This commit is contained in:
129
lib/blacklist.c
Normal file
129
lib/blacklist.c
Normal file
@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Blacklist Copyright 2013 Regents of the University of Michigan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
#include "blacklist.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include "constraint.h"
|
||||
#include "logger.h"
|
||||
|
||||
#define ADDR_DISALLOWED 0
|
||||
#define ADDR_ALLOWED 1
|
||||
|
||||
static constraint_t *constraint = NULL;
|
||||
|
||||
// check whether a single IP address is allowed to be scanned.
|
||||
// 1 => is allowed
|
||||
// 0 => is not allowed
|
||||
int blacklist_is_allowed(uint32_t s_addr) {
|
||||
return constraint_lookup_ip(constraint, ntohl(s_addr)) == ADDR_ALLOWED;
|
||||
}
|
||||
|
||||
// blacklist a CIDR network allocation
|
||||
// e.g. blacklist_add("128.255.134.0", 24)
|
||||
void blacklist_prefix(char *ip, int prefix_len)
|
||||
{
|
||||
assert(constraint);
|
||||
constraint_set(constraint, ntohl(inet_addr(ip)), prefix_len, ADDR_DISALLOWED);
|
||||
}
|
||||
|
||||
// whitelist a CIDR network allocation
|
||||
void whitelist_prefix(char *ip, int prefix_len)
|
||||
{
|
||||
assert(constraint);
|
||||
constraint_set(constraint, ntohl(inet_addr(ip)), prefix_len, ADDR_ALLOWED);
|
||||
}
|
||||
|
||||
static int init(char *file, const char *name, int value)
|
||||
{
|
||||
FILE *fp;
|
||||
char line[1000];
|
||||
|
||||
fp = fopen(file, "r");
|
||||
if (fp == NULL) {
|
||||
log_fatal(name, "Unable to open %s file: %s: %s", name, file, strerror(errno));
|
||||
}
|
||||
|
||||
while (fgets(line, sizeof(line), fp) != NULL) {
|
||||
char *comment = strchr(line, '#');
|
||||
if (comment) {
|
||||
*comment = '\0';
|
||||
}
|
||||
char ip[33];
|
||||
if ((sscanf(line, "%32s", ip)) == EOF) {
|
||||
continue;
|
||||
}
|
||||
int prefix_len = 32;
|
||||
char *slash = strchr(ip, '/');
|
||||
if (slash) { // split apart network and prefix length
|
||||
*slash = '\0';
|
||||
char *end;
|
||||
char *len = slash+1;
|
||||
errno = 0;
|
||||
prefix_len = strtol(len, &end, 10);
|
||||
if (end == len || errno != 0 || prefix_len < 0 || prefix_len > 32) {
|
||||
log_fatal(name, "Unable to parse %s file: %s ('%s' is not a valid prefix length)", name, file, len);
|
||||
}
|
||||
}
|
||||
struct in_addr addr;
|
||||
if (inet_aton(ip, &addr) == 0) {
|
||||
log_fatal(name, "Unable to parse %s file: %s ('%s' is not a valid IP address)", name, file, ip);
|
||||
}
|
||||
constraint_set(constraint, ntohl(addr.s_addr), prefix_len, value);
|
||||
log_trace(name, "%sing %s/%i",
|
||||
name, ip, prefix_len);
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t blacklist_count_allowed()
|
||||
{
|
||||
assert(constraint);
|
||||
return constraint_count_ips(constraint, ADDR_ALLOWED);
|
||||
}
|
||||
|
||||
uint64_t blacklist_count_not_allowed()
|
||||
{
|
||||
assert(constraint);
|
||||
return constraint_count_ips(constraint, ADDR_DISALLOWED);
|
||||
}
|
||||
|
||||
|
||||
// Initialize address constraints from whitelist and blacklist files.
|
||||
// Either can be set to NULL to omit.
|
||||
int blacklist_init_from_files(char *whitelist_filename, char *blacklist_filename)
|
||||
{
|
||||
assert(!constraint);
|
||||
if (whitelist_filename) {
|
||||
// using a whitelist, so default to allowing nothing
|
||||
constraint = constraint_init(ADDR_DISALLOWED);
|
||||
log_trace("whitelist", "blacklisting 0.0.0.0/0");
|
||||
init(whitelist_filename, "whitelist", ADDR_ALLOWED);
|
||||
} else {
|
||||
// no whitelist, so default to allowing everything
|
||||
constraint = constraint_init(ADDR_ALLOWED);
|
||||
}
|
||||
if (blacklist_filename) {
|
||||
init(blacklist_filename, "blacklist", ADDR_DISALLOWED);
|
||||
}
|
||||
constraint_optimize(constraint);
|
||||
uint64_t allowed = blacklist_count_allowed();
|
||||
log_debug("blacklist", "%lu addresses allowed to be scanned (%0.0f%% of address space)",
|
||||
allowed, allowed*100./(1L << 32));
|
||||
return 0;
|
||||
}
|
13
lib/blacklist.h
Normal file
13
lib/blacklist.h
Normal file
@ -0,0 +1,13 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef _BLACKLIST_H
|
||||
#define _BLACKLIST_H
|
||||
|
||||
int blacklist_is_allowed(uint32_t s_addr);
|
||||
void blacklist_prefix(char *ip, int prefix_len);
|
||||
void whitelist_prefix(char *ip, int prefix_len);
|
||||
int blacklist_init_from_files(char *whitelist, char*blacklist);
|
||||
uint64_t blacklist_count_allowed();
|
||||
uint64_t blacklist_count_not_allowed();
|
||||
|
||||
#endif
|
384
lib/constraint.c
Normal file
384
lib/constraint.c
Normal file
@ -0,0 +1,384 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "../lib/constraint.h"
|
||||
#include "../lib/logger.h"
|
||||
|
||||
//
|
||||
// Efficient address-space constraints (AH 7/2013)
|
||||
//
|
||||
// This module uses a tree-based representation to efficiently
|
||||
// manipulate and query constraints on the address space to be
|
||||
// scanned. It provides a value for every IP address, and these
|
||||
// values are applied by setting them for network prefixes. Order
|
||||
// matters: setting a value replaces any existing value for that
|
||||
// prefix or subsets of it. We use this to implement network
|
||||
// whitelisting and blacklisting.
|
||||
//
|
||||
// Think of setting values in this structure like painting
|
||||
// subnets with different colors. We can paint subnets black to
|
||||
// exclude them and white to allow them. Only the top color shows.
|
||||
// This makes for potentially very powerful constraint specifications.
|
||||
//
|
||||
// Internally, this is implemented using a binary tree, where each
|
||||
// node corresponds to a network prefix. (E.g., the root is
|
||||
// 0.0.0.0/0, and its children, if present, are 0.0.0.0/1 and
|
||||
// 128.0.0.0/1.) Each leaf of the tree stores the value that applies
|
||||
// to every address within the leaf's portion of the prefix space.
|
||||
//
|
||||
// As an optimization, after all values are set, we look up the
|
||||
// value or subtree for every /16 prefix and cache them as an array.
|
||||
// This lets subsequent lookups bypass the bottom half of the tree.
|
||||
//
|
||||
|
||||
/*
|
||||
* Constraint Copyright 2013 Regents of the University of Michigan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
typedef struct node {
|
||||
struct node *l;
|
||||
struct node *r;
|
||||
value_t value;
|
||||
} node_t;
|
||||
|
||||
// As an optimization, we precompute lookups for every prefix of this
|
||||
// length:
|
||||
#define RADIX_LENGTH 16
|
||||
|
||||
struct _constraint {
|
||||
node_t *root; // root node of the tree
|
||||
node_t **radix; // array of nodes for every RADIX_LENGTH prefix
|
||||
int optimized; // is radix populated and up-to-date?
|
||||
};
|
||||
|
||||
// Tree operations respect the invariant that every node that isn't a
|
||||
// leaf has exactly two children.
|
||||
#define IS_LEAF(node) ((node)->l == NULL)
|
||||
|
||||
// Allocate a new leaf with the given value
|
||||
static node_t* _create_leaf(value_t value)
|
||||
{
|
||||
node_t *node = malloc(sizeof(node_t));
|
||||
assert(node);
|
||||
node->l = NULL;
|
||||
node->r = NULL;
|
||||
node->value = value;
|
||||
return node;
|
||||
}
|
||||
|
||||
// Free the subtree rooted at node.
|
||||
static void _destroy_subtree(node_t *node)
|
||||
{
|
||||
if (node == NULL)
|
||||
return;
|
||||
_destroy_subtree(node->l);
|
||||
_destroy_subtree(node->r);
|
||||
free(node);
|
||||
}
|
||||
|
||||
// Convert from an internal node to a leaf.
|
||||
static void _convert_to_leaf(node_t *node)
|
||||
{
|
||||
assert(node);
|
||||
assert(!IS_LEAF(node));
|
||||
_destroy_subtree(node->l);
|
||||
_destroy_subtree(node->r);
|
||||
node->l = NULL;
|
||||
node->r = NULL;
|
||||
}
|
||||
|
||||
// Recursive function to set value for a given network prefix within
|
||||
// the tree. (Note: prefix must be in host byte order.)
|
||||
static void _set_recurse(node_t *node, uint32_t prefix, int len, value_t value)
|
||||
{
|
||||
assert(node);
|
||||
assert(0 <= len && len <= 32);
|
||||
|
||||
if (len == 0) {
|
||||
// We're at the end of the prefix; make this a leaf and set the value.
|
||||
if (!IS_LEAF(node)) {
|
||||
_convert_to_leaf(node);
|
||||
}
|
||||
node->value = value;
|
||||
return;
|
||||
}
|
||||
|
||||
if (IS_LEAF(node)) {
|
||||
// We're not at the end of the prefix, but we hit a leaf.
|
||||
if (node->value == value) {
|
||||
// A larger prefix has the same value, so we're done.
|
||||
return;
|
||||
}
|
||||
// The larger prefix has a different value, so we need to convert it
|
||||
// into an internal node and continue processing on one of the leaves.
|
||||
node->l = _create_leaf(node->value);
|
||||
node->r = _create_leaf(node->value);
|
||||
}
|
||||
|
||||
// We're not at the end of the prefix, and we're at an internal
|
||||
// node. Recurse on the left or right subtree.
|
||||
if (prefix & 0x80000000) {
|
||||
_set_recurse(node->r, prefix << 1, len - 1, value);
|
||||
} else {
|
||||
_set_recurse(node->l, prefix << 1, len - 1, value);
|
||||
}
|
||||
|
||||
// At this point, we're an internal node, and the value is set
|
||||
// by one of our children or its descendent. If both children are
|
||||
// leaves with the same value, we can discard them and become a left.
|
||||
if (IS_LEAF(node->r) && IS_LEAF(node->l) && node->r->value == node->l->value) {
|
||||
node->value = node->l->value;
|
||||
_convert_to_leaf(node);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the value for a given network prefix, overwriting any existing
|
||||
// values on that prefix or subsets of it.
|
||||
// (Note: prefix must be in host byte order.)
|
||||
void constraint_set(constraint_t *con, uint32_t prefix, int len, value_t value)
|
||||
{
|
||||
assert(con);
|
||||
_set_recurse(con->root, prefix, len, value);
|
||||
con->optimized = 0;
|
||||
}
|
||||
|
||||
// Return the value pertaining to an address, according to the tree
|
||||
// starting at given root. (Note: address must be in host byte order.)
|
||||
static int _lookup_ip(node_t *root, uint32_t address)
|
||||
{
|
||||
assert(root);
|
||||
node_t *node = root;
|
||||
uint32_t mask = 0x80000000;
|
||||
for (;;) {
|
||||
if (IS_LEAF(node)) {
|
||||
return node->value;
|
||||
}
|
||||
if (address & mask) {
|
||||
node = node->r;
|
||||
} else {
|
||||
node = node->l;
|
||||
}
|
||||
mask >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Return the value pertaining to an address.
|
||||
// (Note: address must be in host byte order.)
|
||||
int constraint_lookup_ip(constraint_t *con, uint32_t address)
|
||||
{
|
||||
assert(con);
|
||||
if (con->optimized) {
|
||||
// Use radix optimization
|
||||
node_t *node = con->radix[address >> (32 - RADIX_LENGTH)];
|
||||
if (IS_LEAF(node)) {
|
||||
return node->value;
|
||||
}
|
||||
return _lookup_ip(node, address << RADIX_LENGTH);
|
||||
} else {
|
||||
// Do a full lookup using the tree
|
||||
log_trace("constraint", "Unoptimized lookup");
|
||||
return _lookup_ip(con->root, address);
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
static uint64_t _count_ips_recurse(node_t *node, value_t value, uint64_t size)
|
||||
{
|
||||
assert(node);
|
||||
if (IS_LEAF(node)) {
|
||||
if (node->value == value) {
|
||||
return size;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return _count_ips_recurse(node->l, value, size >> 1) +
|
||||
_count_ips_recurse(node->r, value, size >> 1);
|
||||
}
|
||||
|
||||
// Return the number of addresses that have a given value.
|
||||
uint64_t constraint_count_ips(constraint_t *con, value_t value)
|
||||
{
|
||||
assert(con);
|
||||
return _count_ips_recurse(con->root, value, (uint64_t)1 << 32);
|
||||
}
|
||||
|
||||
// Initialize the tree.
|
||||
// All addresses will initally have the given value.
|
||||
constraint_t* constraint_init(value_t value)
|
||||
{
|
||||
log_trace("constraint", "Initializing");
|
||||
constraint_t* con = malloc(sizeof(constraint_t));
|
||||
con->root = _create_leaf(value);
|
||||
con->radix = calloc(sizeof(node_t *), 1 << RADIX_LENGTH);
|
||||
assert(con->radix);
|
||||
con->optimized = 0;
|
||||
return con;
|
||||
}
|
||||
|
||||
// Deinitialize and free the tree.
|
||||
void constraint_free(constraint_t *con)
|
||||
{
|
||||
assert(con);
|
||||
log_trace("constraint", "Cleaning up");
|
||||
_destroy_subtree(con->root);
|
||||
free(con->radix);
|
||||
free(con);
|
||||
}
|
||||
|
||||
// Return a node that determines the values for the addresses with
|
||||
// the given prefix. This is either the internal node that
|
||||
// corresponds to the end of the prefix or a leaf node that
|
||||
// encompasses the prefix. (Note: prefix must be in host byte order.)
|
||||
static node_t* _lookup_node(node_t *root, uint32_t prefix, int len)
|
||||
{
|
||||
assert(root);
|
||||
assert(0 <= len && len <= 32);
|
||||
|
||||
node_t *node = root;
|
||||
uint32_t mask = 0x80000000;
|
||||
|
||||
for (int i=0; i < len; i++) {
|
||||
if (IS_LEAF(node)) {
|
||||
return node;
|
||||
}
|
||||
if (prefix & mask) {
|
||||
node = node->r;
|
||||
} else {
|
||||
node = node->l;
|
||||
}
|
||||
mask >>= 1;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
// After values have been set, precompute prefix lookups.
|
||||
void constraint_optimize(constraint_t *con)
|
||||
{
|
||||
assert(con);
|
||||
if (con->optimized) {
|
||||
return;
|
||||
}
|
||||
log_trace("constraint", "Optimizing constraints");
|
||||
for (uint32_t i=0; i < (1 << RADIX_LENGTH); i++) {
|
||||
uint32_t prefix = i << (32 - RADIX_LENGTH);
|
||||
con->radix[i] = _lookup_node(con->root, prefix, RADIX_LENGTH);
|
||||
}
|
||||
con->optimized = 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
int main(void)
|
||||
{
|
||||
log_init(stderr, LOG_DEBUG);
|
||||
|
||||
constraint_t *con = constraint_init(0);
|
||||
constraint_set(con, ntohl(inet_addr("128.128.0.0")), 1, 22);
|
||||
constraint_set(con, ntohl(inet_addr("128.128.0.0")), 1, 1);
|
||||
constraint_set(con, ntohl(inet_addr("128.0.0.0")), 1, 1);
|
||||
constraint_set(con, ntohl(inet_addr("10.0.0.0")), 24, 1);
|
||||
constraint_set(con, ntohl(inet_addr("10.0.0.0")), 24, 0);
|
||||
constraint_set(con, ntohl(inet_addr("10.11.12.0")), 24, 1);
|
||||
constraint_set(con, ntohl(inet_addr("141.212.0.0")), 16, 0);
|
||||
|
||||
for (int x=1; x < 2; x++) {
|
||||
if (x == 1) {
|
||||
constraint_optimize(con);
|
||||
}
|
||||
|
||||
printf("count(0)=%ld\n", constraint_count_ips(con, 0));
|
||||
printf("count(1)=%ld\n", constraint_count_ips(con, 1));
|
||||
printf("%d\n", constraint_lookup_ip(con,ntohl(inet_addr("10.11.12.0"))));
|
||||
assert(constraint_count_ips(con, 0) + constraint_count_ips(con, 1) == (uint64_t)1 << 32);
|
||||
|
||||
uint32_t i=0, count=0;
|
||||
do {
|
||||
if (constraint_lookup_ip(con, i))
|
||||
count++;
|
||||
} while (++i != 0);
|
||||
printf("derived count(1)=%u\n", count);
|
||||
}
|
||||
|
||||
constraint_free(con);
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
static int init(constraint_t *con, char *file, const char *name, value_t value)
|
||||
{
|
||||
FILE *fp;
|
||||
char line[1000];
|
||||
int blocked = 0;
|
||||
|
||||
fp = fopen(file, "r");
|
||||
if (fp == NULL) {
|
||||
log_fatal(name, "Unable to open %s file: %s: %s",
|
||||
name, file, strerror(errno));
|
||||
}
|
||||
|
||||
while (fgets(line, sizeof(line), fp) != NULL) {
|
||||
char *comment = strchr(line, '#');
|
||||
if (comment) {
|
||||
*comment = '\0';
|
||||
}
|
||||
char ip[33];
|
||||
if ((sscanf(line, "%32s", ip)) == EOF) {
|
||||
continue;
|
||||
}
|
||||
int prefix_len;
|
||||
char *slash = strchr(ip, '/');
|
||||
if (slash == NULL) {
|
||||
log_fatal(name,
|
||||
"Unable to parse %s file: %s",
|
||||
name, file);
|
||||
}
|
||||
// split apart network and prefix length
|
||||
*slash = '\0';
|
||||
prefix_len = atoi(&slash[1]);
|
||||
constraint_set(con, ntohl(inet_addr(ip)), prefix_len, value);
|
||||
|
||||
blocked++;
|
||||
}
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
log_init(stderr, LOG_TRACE);
|
||||
|
||||
constraint_t *con = constraint_init(1);
|
||||
init(con, "blacklist.prefixes", "blacklist", 0);
|
||||
//constraint_optimize(con);
|
||||
|
||||
printf("count(0)=%lu\n", constraint_count_ips(con, 0));
|
||||
printf("count(1)=%lu\n", constraint_count_ips(con, 1));
|
||||
|
||||
uint32_t i=0, count=0;
|
||||
do {
|
||||
if (constraint_lookup_ip(con, i))
|
||||
count++;
|
||||
} while (++i != 0);
|
||||
printf("derived count(1)=%u\n", count);
|
||||
|
||||
constraint_free(con);
|
||||
|
||||
}
|
||||
|
||||
*/
|
14
lib/constraint.h
Normal file
14
lib/constraint.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef _CONSTRAINT_H
|
||||
#define _CONSTRAINT_H
|
||||
|
||||
typedef struct _constraint constraint_t;
|
||||
typedef int value_t;
|
||||
|
||||
constraint_t* constraint_init(value_t value);
|
||||
void constraint_free(constraint_t *con);
|
||||
void constraint_set(constraint_t *con, uint32_t prefix, int len, value_t value);
|
||||
void constraint_optimize(constraint_t *con);
|
||||
int constraint_lookup_ip(constraint_t *con, uint32_t address);
|
||||
uint64_t constraint_count_ips(constraint_t *con, value_t value);
|
||||
|
||||
#endif //_CONSTRAINT_H
|
126
lib/logger.c
Normal file
126
lib/logger.c
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Logger Copyright 2013 Regents of the University of Michigan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
#ifndef HEADER_ZUTIL_LOGGER_H
|
||||
#define HEADER_ZUTIL_LOGGER_H
|
||||
|
||||
static enum LogLevel log_output_level = LOG_INFO;
|
||||
|
||||
static FILE *log_output_stream = NULL;
|
||||
|
||||
static const char *log_level_name[] = {
|
||||
"FATAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" };
|
||||
|
||||
static int LogLogVA(enum LogLevel level, const char *loggerName,
|
||||
const char *logMessage, va_list args)
|
||||
{
|
||||
if (!log_output_stream) {
|
||||
log_output_stream = stdout;
|
||||
}
|
||||
if (level <= log_output_level) {
|
||||
const char *levelName = log_level_name[level];
|
||||
assert(level < sizeof(log_level_name));
|
||||
|
||||
struct timeval now;
|
||||
char timestamp[256];
|
||||
gettimeofday(&now, NULL);
|
||||
time_t sec = now.tv_sec;
|
||||
struct tm* ptm = localtime(&sec);
|
||||
strftime(timestamp, 20, "%b %d %H:%M:%S", ptm);
|
||||
fprintf(log_output_stream, "%s.%03ld [%s] ",
|
||||
timestamp, now.tv_usec/1000, levelName);
|
||||
if (loggerName) {
|
||||
fprintf(log_output_stream, "%s: ", loggerName);
|
||||
}
|
||||
if (logMessage) {
|
||||
vfprintf(log_output_stream, logMessage, args);
|
||||
}
|
||||
if (loggerName || logMessage) {
|
||||
fputs("\n", log_output_stream);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int log_fatal(const char *name, const char *message, ...) {
|
||||
va_list va; va_start(va, message);
|
||||
LogLogVA(LOG_FATAL, name, message, va);
|
||||
va_end(va);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int log_error(const char *name, const char *message, ...) {
|
||||
va_list va; va_start(va, message);
|
||||
int ret = LogLogVA(LOG_ERROR, name, message, va);
|
||||
va_end(va);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int log_warn(const char *name, const char *message, ...) {
|
||||
va_list va; va_start(va, message);
|
||||
int ret = LogLogVA(LOG_WARN, name, message, va);
|
||||
va_end(va);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int log_info(const char *name, const char *message, ...) {
|
||||
va_list va; va_start(va, message);
|
||||
int ret = LogLogVA(LOG_INFO, name, message, va);
|
||||
va_end(va);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int log_debug(const char *name, const char *message, ...) {
|
||||
va_list va; va_start(va, message);
|
||||
int ret = LogLogVA(LOG_DEBUG, name, message, va);
|
||||
va_end(va);
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern int log_trace(const char *name, const char *message, ...) {
|
||||
va_list va; va_start(va, message);
|
||||
int ret = LogLogVA(LOG_TRACE, name, message, va);
|
||||
va_end(va);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int log_init(FILE *stream, enum LogLevel level)
|
||||
{
|
||||
log_output_stream = stream;
|
||||
log_output_level = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
double now(void)
|
||||
{
|
||||
struct timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
return (double)now.tv_sec + (double)now.tv_usec/1000000.;
|
||||
}
|
||||
|
||||
size_t dstrftime(char *buf, size_t maxsize, const char *format, double tm)
|
||||
{
|
||||
struct timeval tv;
|
||||
double tm_floor;
|
||||
tm_floor = floor(tm);
|
||||
tv.tv_sec = (long) tm_floor;
|
||||
tv.tv_usec = (long) (tm - floor(tm)) * 1000000;
|
||||
return strftime(buf, maxsize, format, localtime((const time_t*) &tv));
|
||||
}
|
||||
|
||||
#endif
|
29
lib/logger.h
Normal file
29
lib/logger.h
Normal file
@ -0,0 +1,29 @@
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifndef _LOGGER_H
|
||||
#define _LOGGER_H
|
||||
|
||||
enum LogLevel { LOG_FATAL, LOG_ERROR, LOG_WARN, LOG_INFO, LOG_DEBUG, LOG_TRACE,
|
||||
NUM_LOGLEVELS };
|
||||
|
||||
int log_fatal(const char *loggerName, const char *logMessage, ...) __attribute__((noreturn));
|
||||
|
||||
int log_error(const char *loggerName, const char *logMessage, ...);
|
||||
|
||||
int log_warn(const char *loggerName, const char *logMessage, ...);
|
||||
|
||||
int log_info(const char *loggerName, const char *logMessage, ...);
|
||||
|
||||
int log_debug(const char *loggerName, const char *logMessage, ...);
|
||||
|
||||
int log_trace(const char *loggerName, const char *logMessage, ...);
|
||||
|
||||
int log_init(FILE *stream, enum LogLevel level);
|
||||
|
||||
size_t dstrftime(char *, size_t, const char *, double);
|
||||
|
||||
double now();
|
||||
|
||||
#endif // _LOGGER_H
|
||||
|
28
lib/random.c
Normal file
28
lib/random.c
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* ZMap Copyright 2013 Regents of the University of Michigan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
#include "random.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define RANDSRC "/dev/urandom"
|
||||
|
||||
int random_bytes(void *dst, size_t n)
|
||||
{
|
||||
FILE *f = fopen(RANDSRC, "rb");
|
||||
assert(f);
|
||||
size_t r = fread(dst, n, 1, f);
|
||||
fclose(f);
|
||||
if (r < 1) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
9
lib/random.h
Normal file
9
lib/random.h
Normal file
@ -0,0 +1,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef _RANDOM_H
|
||||
#define _RANDOM_H
|
||||
|
||||
int random_bytes(void *dst, size_t n);
|
||||
|
||||
#endif
|
261
lib/redis.c
Normal file
261
lib/redis.c
Normal file
@ -0,0 +1,261 @@
|
||||
/*
|
||||
* ZMap Redis Helpers Copyright 2013 Regents of the University of Michigan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "redis.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "assert.h"
|
||||
#include "logger.h"
|
||||
#include <stdint.h>
|
||||
#include <hiredis/hiredis.h>
|
||||
|
||||
#define REDIS_UNIX_PATH "/tmp/redis.sock"
|
||||
#define REDIS_TIMEOUT 2
|
||||
|
||||
#undef MIN
|
||||
#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
|
||||
|
||||
static redisContext *rctx;
|
||||
|
||||
static redisContext* redis_connect(void)
|
||||
{
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = REDIS_TIMEOUT;
|
||||
timeout.tv_usec = 0;
|
||||
return (redisContext*) redisConnectUnixWithTimeout(REDIS_UNIX_PATH,
|
||||
timeout);
|
||||
}
|
||||
|
||||
static int chkerr(redisReply *reply)
|
||||
{
|
||||
assert(rctx);
|
||||
if (reply == NULL || reply->type == REDIS_REPLY_ERROR) {
|
||||
log_error("redis", "an error occurred when "
|
||||
"retreiving item from redis: %s",
|
||||
rctx->errstr);
|
||||
if (reply) {
|
||||
freeReplyObject(reply);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int redis_init(void)
|
||||
{
|
||||
rctx = redis_connect();
|
||||
if (!rctx) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int redis_close(void)
|
||||
{
|
||||
redisFree(rctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
redisContext* redis_get_context(void)
|
||||
{
|
||||
return rctx;
|
||||
}
|
||||
|
||||
int redis_flush(void)
|
||||
{
|
||||
redisReply *reply = (redisReply*) redisCommand(rctx, "FLUSHDB");
|
||||
if (chkerr(reply)) {
|
||||
return -1;
|
||||
}
|
||||
freeReplyObject(reply);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int redis_existconf(const char *name)
|
||||
{
|
||||
assert(rctx);
|
||||
redisReply *reply = (redisReply*) redisCommand(rctx, "EXISTS %s", name);
|
||||
if (chkerr(reply)) {
|
||||
return -1;
|
||||
}
|
||||
int v = reply->integer;
|
||||
freeReplyObject(reply);
|
||||
return v;
|
||||
}
|
||||
|
||||
int redis_delconf(const char *name)
|
||||
{
|
||||
assert(rctx);
|
||||
redisReply *reply = (redisReply*) redisCommand(rctx, "DEL %s", name);
|
||||
if (chkerr(reply)) {
|
||||
return -1;
|
||||
}
|
||||
freeReplyObject(reply);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int redis_setconf(const char *name, char *value)
|
||||
{
|
||||
assert(rctx);
|
||||
redisReply *reply = (redisReply*) redisCommand(rctx, "SET %s %s",
|
||||
name, value);
|
||||
if (chkerr(reply)) {
|
||||
return -1;
|
||||
}
|
||||
freeReplyObject(reply);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int redis_getconf(const char *name, char *buf, size_t maxlen)
|
||||
{
|
||||
assert(rctx);
|
||||
redisReply *reply = (redisReply*) redisCommand(rctx, "GET %s", name);
|
||||
if (chkerr(reply)) {
|
||||
return -1;
|
||||
}
|
||||
strncpy(buf, reply->str, maxlen);
|
||||
freeReplyObject(reply);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t redis_getconf_uint32_t(const char *key)
|
||||
{
|
||||
assert(rctx);
|
||||
char buf[50];
|
||||
redis_getconf(key, buf, 50);
|
||||
return atoi(buf);
|
||||
}
|
||||
|
||||
int redis_setconf_uint32_t(const char *key, uint32_t value)
|
||||
{
|
||||
assert(rctx);
|
||||
char buf[50];
|
||||
sprintf(buf, "%u", value);
|
||||
return redis_setconf(key, buf);
|
||||
}
|
||||
|
||||
|
||||
static long redis_get_sizeof(const char *cmd, const char *name)
|
||||
{
|
||||
assert(rctx);
|
||||
redisReply *reply;
|
||||
reply = (redisReply*) redisCommand(rctx, "%s %s", cmd, name);
|
||||
assert(reply);
|
||||
assert(reply->type == REDIS_REPLY_INTEGER);
|
||||
long rtr = reply->integer;
|
||||
freeReplyObject(reply);
|
||||
return rtr;
|
||||
}
|
||||
|
||||
long redis_get_sizeof_list(const char *name)
|
||||
{
|
||||
return redis_get_sizeof("LLEN", name);
|
||||
}
|
||||
|
||||
long redis_get_sizeof_set(const char *name)
|
||||
{
|
||||
return redis_get_sizeof("SCARD", name);
|
||||
}
|
||||
|
||||
int redis_pull(char *redisqueuename, void *buf,
|
||||
int maxload, size_t obj_size, int *numloaded, const char* cmd)
|
||||
{
|
||||
assert(rctx);
|
||||
long elems_in_redis = redis_get_sizeof_list(redisqueuename);
|
||||
long num_to_add = MIN(elems_in_redis, maxload);
|
||||
log_info("redis", "INFO: redis load called on %s. Transfering %li "
|
||||
"of %li elements to in-memory queue.",
|
||||
redisqueuename,
|
||||
num_to_add, elems_in_redis);
|
||||
for(int i=0; i < num_to_add; i++) {
|
||||
redisAppendCommand(rctx, "%s %s", cmd, redisqueuename);
|
||||
}
|
||||
for(int i=0; i < num_to_add; i++) {
|
||||
redisReply *reply;
|
||||
int rc = redisGetReply(rctx, (void**) &reply);
|
||||
if (rc != REDIS_OK) {
|
||||
log_fatal("redis", "response from redis != REDIS_OK");
|
||||
return -1;
|
||||
}
|
||||
if (!reply) {
|
||||
log_fatal("redis", "no reply provided by redis.");
|
||||
return -1;
|
||||
}
|
||||
if (reply->type != REDIS_REPLY_STRING) {
|
||||
log_fatal("redis",
|
||||
"unxpected reply type from redis.");
|
||||
return -1;
|
||||
}
|
||||
if ((size_t)reply->len != obj_size) {
|
||||
log_fatal("redis", "ERROR: unexpected lengthed "
|
||||
"object provided by redis.\n");
|
||||
return -1;
|
||||
}
|
||||
memcpy((void*)((intptr_t)buf+i*obj_size), reply->str, obj_size);
|
||||
freeReplyObject(reply);
|
||||
}
|
||||
*numloaded = num_to_add;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int redis_lpull(char *redisqueuename, void *buf,
|
||||
int maxload, size_t obj_size, int *numloaded)
|
||||
{
|
||||
return redis_pull(redisqueuename, buf,
|
||||
maxload, obj_size, numloaded, "LPOP");
|
||||
}
|
||||
|
||||
int redis_spull(char *redisqueuename, void *buf,
|
||||
int maxload, size_t obj_size, int *numloaded)
|
||||
{
|
||||
return redis_pull(redisqueuename, buf,
|
||||
maxload, obj_size, numloaded, "SRAND");
|
||||
}
|
||||
|
||||
static int redis_push(char *redisqueuename,
|
||||
void *buf, int num, size_t len, const char *cmd)
|
||||
{
|
||||
assert(rctx);
|
||||
for (int i=0; i < num; i++) {
|
||||
void* load = (void*)((intptr_t)buf + i*len);
|
||||
int rc = redisAppendCommand(rctx, "%s %s %b",
|
||||
cmd, redisqueuename, load, len);
|
||||
if (rc != REDIS_OK || rctx->err) {
|
||||
log_fatal("redis", "%s", rctx->errstr);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
redisReply *reply;
|
||||
for (int i=0; i < num; i++) {
|
||||
if (redisGetReply(rctx, (void**) &reply) != REDIS_OK
|
||||
|| rctx->err) {
|
||||
log_fatal("redis","%s", rctx->errstr);
|
||||
return -1;
|
||||
}
|
||||
if (reply->type == REDIS_REPLY_ERROR) {
|
||||
log_fatal("redis", "%s", rctx->errstr);
|
||||
return -1;
|
||||
}
|
||||
freeReplyObject(reply);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int redis_lpush(char *redisqueuename,
|
||||
void *buf, int num, size_t len)
|
||||
{
|
||||
return redis_push(redisqueuename, buf, num, len, "RPUSH");
|
||||
}
|
||||
|
||||
int redis_spush(char *redisqueuename,
|
||||
void *buf, int num, size_t len)
|
||||
{
|
||||
return redis_push(redisqueuename, buf, num, len, "SADD");
|
||||
}
|
||||
|
40
lib/redis.h
Normal file
40
lib/redis.h
Normal file
@ -0,0 +1,40 @@
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <hiredis/hiredis.h>
|
||||
|
||||
#ifndef _REDIS_ZHELPERS_H
|
||||
#define _REDIS_ZHELPERS_H
|
||||
|
||||
int redis_init(void);
|
||||
|
||||
int redis_close(void);
|
||||
|
||||
int redis_existconf(const char*);
|
||||
|
||||
int redis_flush(void);
|
||||
|
||||
int redis_delconf(const char*);
|
||||
|
||||
int redis_setconf(const char*, char*);
|
||||
|
||||
int redis_getconf(const char*, char*, size_t);
|
||||
|
||||
long redis_get_sizeof_list(const char*);
|
||||
|
||||
long redis_get_sizeof_set(const char*);
|
||||
|
||||
int redis_lpush(char*, void*, int, size_t);
|
||||
|
||||
int redis_lpull(char*, void*, int, size_t, int*);
|
||||
|
||||
int redis_spull(char*, void*, int, size_t, int*);
|
||||
|
||||
int redis_spush(char*, void*, int, size_t);
|
||||
|
||||
redisContext* redis_get_context(void);
|
||||
|
||||
uint32_t redis_getconf_uint32_t(const char*);
|
||||
|
||||
int redis_setconf_uint32_t(const char*, uint32_t);
|
||||
|
||||
#endif // _REDIS_ZHELPERS_H
|
1400
lib/rijndael-alg-fst.c
Normal file
1400
lib/rijndael-alg-fst.c
Normal file
File diff suppressed because it is too large
Load Diff
47
lib/rijndael-alg-fst.h
Normal file
47
lib/rijndael-alg-fst.h
Normal file
@ -0,0 +1,47 @@
|
||||
/**
|
||||
* rijndael-alg-fst.h
|
||||
*
|
||||
* @version 3.0 (December 2000)
|
||||
*
|
||||
* Optimised ANSI C code for the Rijndael cipher (now AES)
|
||||
*
|
||||
* @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
|
||||
* @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
|
||||
* @author Paulo Barreto <paulo.barreto@terra.com.br>
|
||||
*
|
||||
* This code is hereby placed in the public domain.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
|
||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef __RIJNDAEL_ALG_FST_H
|
||||
#define __RIJNDAEL_ALG_FST_H
|
||||
|
||||
#define MAXKC (256/32)
|
||||
#define MAXKB (256/8)
|
||||
#define MAXNR 14
|
||||
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned int u32;
|
||||
|
||||
int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits);
|
||||
int rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits);
|
||||
void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 ct[16]);
|
||||
void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16], u8 pt[16]);
|
||||
|
||||
#ifdef INTERMEDIATE_VALUE_KAT
|
||||
void rijndaelEncryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds);
|
||||
void rijndaelDecryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds);
|
||||
#endif /* INTERMEDIATE_VALUE_KAT */
|
||||
|
||||
#endif /* __RIJNDAEL_ALG_FST_H */
|
Reference in New Issue
Block a user