@ -2,73 +2,137 @@
# include <stdio.h>
# include <string.h>
# include <ctype.h>
# include <arpa/inet.h>
# include <jansson.h>
# include "conf.h"
static char *
skipspaces ( char * p ) {
while ( isspace ( * p ) ) p + + ;
return p ;
}
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 ;
FILE * f = fopen ( filename , " r " ) ;
if ( ! f ) {
return NULL ;
}
/* 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 ;
while ( ! feof ( f ) ) {
char buffer [ 100 ] , * ret ;
memset ( buffer , 0 , sizeof ( buffer ) ) ;
if ( ! ( ret = fgets ( buffer , sizeof ( buffer ) - 1 , f ) ) ) {
break ;
}
if ( * ret = = ' # ' ) { /* comments */
continue ;
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 ) {
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 ) {
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 ;
unsigned short mask_bits = 0 ;
struct disabled_command * dc ;
json_t * val = json_object_iter_value ( kv ) ;
if ( * ret ! = 0 ) {
ret [ strlen ( ret ) - 1 ] = 0 ; /* remove new line */
if ( json_typeof ( val ) ! = JSON_ARRAY ) {
continue ; /* TODO: report error? */
}
if ( strncmp ( ret , " redis_host " , 10 ) = = 0 ) {
conf - > redis_host = strdup ( skipspaces ( ret + 11 ) ) ;
} else if ( strncmp ( ret , " redis_port " , 10 ) = = 0 ) {
conf - > redis_port = ( short ) atoi ( skipspaces ( ret + 10 ) ) ;
} else if ( strncmp ( ret , " http_host " , 10 ) = = 0 ) {
conf - > http_host = strdup ( skipspaces ( ret + 11 ) ) ;
} else if ( strncmp ( ret , " http_port " , 9 ) = = 0 ) {
conf - > http_port = ( short ) atoi ( skipspaces ( ret + 10 ) ) ;
/* parse key in format "ip/mask" */
s = json_object_iter_key ( kv ) ;
p = strchr ( s , ' / ' ) ;
if ( ! p ) {
ip = strdup ( s ) ;
} else {
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 ) {
json_t * jelem = json_array_get ( val , ( size_t ) i ) ;
if ( json_typeof ( jelem ) = = JSON_STRING ) {
n + + ;
}
}
}
fclose ( f ) ;
/* default values */
if ( ! conf - > redis_host ) {
conf - > redis_host = strdup ( " 127.0.0.1 " ) ;
}
if ( ! conf - > http_host ) {
conf - > http_host = strdup ( " 0.0.0.0 " ) ;
/* allocate block */
dc = calloc ( 1 , sizeof ( struct disabled_command ) ) ;
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 ) {
size_t sz ;
s = json_string_value ( jelem ) ;
sz = strlen ( s ) ;
dc - > commands [ cur ] = calloc ( 1 + sz , 1 ) ;
memcpy ( dc - > commands [ cur ] , s , sz ) ;
cur + + ;
}
}
}
return conf ;
return root ;
}
void
conf_free ( struct conf * conf ) {
free ( conf - > redis_host ) ;
free ( conf - > redis_auth ) ;
free ( conf - > http_host ) ;
free ( conf ) ;