You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

140 lines
3.5 KiB
C

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <arpa/inet.h>
#include <jansson.h>
#include "conf.h"
static struct disabled_command *
conf_disable_commands(json_t *jtab);
struct conf *
conf_read(const char *filename) {
json_t *j;
json_error_t error;
struct conf *conf;
void *kv;
/* defaults */
conf = calloc(1, sizeof(struct conf));
conf->redis_host = strdup("127.0.0.1");
conf->redis_port = 6379;
conf->http_host = strdup("0.0.0.0");
conf->http_port = 7379;
j = json_load_file(filename, 0, &error);
if(!j) {
fprintf(stderr, "Error: %s (line %d)\n", error.text, error.line);
return conf;
}
for(kv = json_object_iter(j); kv; kv = json_object_iter_next(j, kv)) {
json_t *jtmp = json_object_iter_value(kv);
if(strcmp(json_object_iter_key(kv), "redis_host") == 0 && json_typeof(jtmp) == JSON_STRING) {
free(conf->redis_host);
conf->redis_host = strdup(json_string_value(jtmp));
} else if(strcmp(json_object_iter_key(kv), "redis_port") == 0 && json_typeof(jtmp) == JSON_INTEGER) {
14 years ago
conf->redis_port = (short)json_integer_value(jtmp);
} else if(strcmp(json_object_iter_key(kv), "redis_auth") == 0 && json_typeof(jtmp) == JSON_STRING) {
conf->redis_auth = strdup(json_string_value(jtmp));
} else if(strcmp(json_object_iter_key(kv), "http_host") == 0 && json_typeof(jtmp) == JSON_STRING) {
free(conf->http_host);
conf->http_host = strdup(json_string_value(jtmp));
} else if(strcmp(json_object_iter_key(kv), "http_port") == 0 && json_typeof(jtmp) == JSON_INTEGER) {
14 years ago
conf->http_port = (short)json_integer_value(jtmp);
} else if(strcmp(json_object_iter_key(kv), "disable") == 0 && json_typeof(jtmp) == JSON_OBJECT) {
conf->disabled = conf_disable_commands(jtmp);
}
}
json_decref(j);
return conf;
}
struct disabled_command *
conf_disable_commands(json_t *jtab) {
struct disabled_command *root = NULL;
void *kv;
for(kv = json_object_iter(jtab); kv; kv = json_object_iter_next(jtab, kv)) {
unsigned int i, cur, n;
char *p, *ip;
const char *s;
in_addr_t mask, subnet;
14 years ago
unsigned short mask_bits = 0;
struct disabled_command *dc;
json_t *val = json_object_iter_value(kv);
if(json_typeof(val) != JSON_ARRAY) {
continue; /* TODO: report error? */
}
/* parse key in format "ip/mask" */
s = json_object_iter_key(kv);
p = strchr(s, '/');
if(!p) {
ip = strdup(s);
} else {
14 years ago
ip = calloc((size_t)(p - s + 1), 1);
memcpy(ip, s, (size_t)(p - s));
mask_bits = (unsigned short)atoi(p+1);
}
mask = (mask_bits == 0 ? 0 : (0xffffffff << (32 - mask_bits)));
subnet = ntohl(inet_addr(ip)) & mask;
/* count strings in the array */
n = 0;
for(i = 0; i < json_array_size(val); ++i) {
14 years ago
json_t *jelem = json_array_get(val, (size_t)i);
if(json_typeof(jelem) == JSON_STRING) {
n++;
}
}
/* allocate block */
dc = calloc(1, sizeof(struct disabled_command));
14 years ago
dc->commands = calloc((size_t)n, sizeof(char*));
dc->subnet = subnet;
dc->mask = mask;
dc->count = n;
dc->next = root;
root = dc;
/* add all disabled commands */
for(i = 0, cur = 0; i < json_array_size(val); ++i) {
json_t *jelem = json_array_get(val, i);
if(json_typeof(jelem) == JSON_STRING) {
14 years ago
size_t sz;
s = json_string_value(jelem);
14 years ago
sz = strlen(s);
dc->commands[cur] = calloc(1 + sz, 1);
memcpy(dc->commands[cur], s, sz);
cur++;
}
}
}
return root;
}
void
conf_free(struct conf *conf) {
free(conf->redis_host);
free(conf->redis_auth);
free(conf->http_host);
free(conf);
}