@ -1,8 +1,10 @@
# include <ctype.h>
# include <getopt.h>
# include "config.h"
# include "mediator.h"
char * config_file_path ;
unsigned int config_interval = MEDIATOR_DEFAULT_INTERVAL ;
uint8_t config_dumpcdr = MEDIATOR_DEFAULT_DUMPCDR ;
uint8_t config_daemonize = MEDIATOR_DEFAULT_DAEMONIZE ;
@ -36,39 +38,108 @@ med_stats_period_t config_stats_period = MEDIATOR_DEFAULT_STATSPERIOD;
int config_maintenance = 0 ;
int strict_leg_tokens = 0 ;
enum config_option {
OPT_CONFIGFILE = ' c ' ,
OPT_DAEMONIZE = ' d ' ,
OPT_PIDFILE = ' D ' ,
OPT_SYSLOG = ' l ' ,
OPT_INTERVAL = ' i ' ,
OPT_MED_HOST = ' h ' ,
OPT_MED_PORT = ' o ' ,
OPT_MED_USER = ' u ' ,
OPT_MED_PASS = ' p ' ,
OPT_MED_DB = ' b ' ,
OPT_CDR_HOST = ' H ' ,
OPT_CDR_PORT = ' O ' ,
OPT_CDR_USER = ' U ' ,
OPT_CDR_PASS = ' P ' ,
OPT_CDR_DB = ' B ' ,
OPT_PROV_HOST = ' S ' ,
OPT_PROV_PORT = ' T ' ,
OPT_PROV_USER = ' R ' ,
OPT_PROV_PASS = ' A ' ,
OPT_PROV_DB = ' N ' ,
OPT_STATS_HOST = ' Z ' ,
OPT_STATS_PORT = ' z ' ,
OPT_STATS_USER = ' W ' ,
OPT_STATS_PASS = ' w ' ,
OPT_STATS_DB = ' X ' ,
OPT_STATS_PERIOD = ' x ' ,
OPT_MAINTENANCE = ' m ' ,
OPT_LEG_TOKENS = ' s ' ,
} ;
static const char options [ ] = " ?c:D:i:dlh:u:p:b:o:H:U:P:B:O:S:T:R:A:N:Z:z:W:w:X:x:ms " ;
struct option long_options [ ] = {
{ " configfile " , required_argument , NULL , OPT_CONFIGFILE } ,
{ " pidfile " , required_argument , NULL , OPT_PIDFILE } ,
{ " daemonize " , no_argument , NULL , OPT_DAEMONIZE } ,
{ " syslog " , no_argument , NULL , OPT_SYSLOG } ,
{ " interval " , required_argument , NULL , OPT_INTERVAL } ,
{ " med-host " , required_argument , NULL , OPT_MED_HOST } ,
{ " med-port " , required_argument , NULL , OPT_MED_PORT } ,
{ " med-user " , required_argument , NULL , OPT_MED_USER } ,
{ " med-pass " , required_argument , NULL , OPT_MED_PASS } ,
{ " med-db " , required_argument , NULL , OPT_MED_DB } ,
{ " cdr-host " , required_argument , NULL , OPT_CDR_HOST } ,
{ " cdr-port " , required_argument , NULL , OPT_CDR_PORT } ,
{ " cdr-user " , required_argument , NULL , OPT_CDR_USER } ,
{ " cdr-pass " , required_argument , NULL , OPT_CDR_PASS } ,
{ " cdr-db " , required_argument , NULL , OPT_CDR_DB } ,
{ " prov-host " , required_argument , NULL , OPT_PROV_HOST } ,
{ " prov-port " , required_argument , NULL , OPT_PROV_PORT } ,
{ " prov-user " , required_argument , NULL , OPT_PROV_USER } ,
{ " prov-pass " , required_argument , NULL , OPT_PROV_PASS } ,
{ " prov-db " , required_argument , NULL , OPT_PROV_DB } ,
{ " stats-host " , required_argument , NULL , OPT_STATS_HOST } ,
{ " stats-port " , required_argument , NULL , OPT_STATS_PORT } ,
{ " stats-user " , required_argument , NULL , OPT_STATS_USER } ,
{ " stats-pass " , required_argument , NULL , OPT_STATS_PASS } ,
{ " stats-db " , required_argument , NULL , OPT_STATS_DB } ,
{ " stats-period " , required_argument , NULL , OPT_STATS_PERIOD } ,
{ " maintenance " , no_argument , NULL , OPT_MAINTENANCE } ,
{ " leg-tokens " , no_argument , NULL , OPT_LEG_TOKENS } ,
{ NULL , 0 , NULL , 0 } ,
} ;
static void config_help ( const char * self , int rc )
{
printf ( " mediator %s - Creates call detail records from OpenSER accounting. \n " \
" Usage: %s [-?] [-d] [-D pidpath] \n " \
" -D \t The path of the PID file (default = '%s'). \n " \
" -d \t Enables daemonization of the process (default = disabled). \n " \
" -l \t Enables dumping of CDRs to syslog (default = disabled). \n " \
" -i \t The creation interval (default = %d). \n " \
" -h \t The ACC db host (default = '%s'). \n " \
" -o \t The ACC db port (default = '%d'). \n " \
" -u \t The ACC db user (default = '%s'). \n " \
" -p \t The ACC db pass (default = '%s'). \n " \
" -b \t The ACC db name (default = '%s'). \n " \
" -H \t The CDR db host (default = '%s'). \n " \
" -O \t The CDR db port (default = '%d'). \n " \
" -U \t The CDR db user (default = '%s'). \n " \
" -P \t The CDR db pass (default = '%s'). \n " \
" -B \t The CDR db name (default = '%s'). \n " \
" -S \t The prov db host (default = '%s'). \n " \
" -T \t The prov db port (default = '%d'). \n " \
" -R \t The prov db user (default = '%s'). \n " \
" -A \t The prov db pass (default = '%s'). \n " \
" -N \t The prov db name (default = '%s'). \n " \
" -Z \t The stats db host (default = '%s'). \n " \
" -z \t The stats db port (default = '%d'). \n " \
" -W \t The stats db user (default = '%s'). \n " \
" -w \t The stats db pass (default = '%s'). \n " \
" -X \t The stats db name (default = '%s'). \n " \
" -x \t The stats db period (default = '%d', 1=hour, 2=day, 3=month). \n " \
" -m \t Maintenance mode (do nothing, just sleep). \n " \
" -s \t Strict acc fields (move to trash otherwise). \n " \
" -? \t Displays this message. \n " ,
MEDIATOR_VERSION , self ,
printf (
" mediator %s - Creates call detail records from OpenSER accounting. \n " \
" Usage: %s [<option>...] \n " \
" \n " \
" Options: \n " \
" -c, --configfile FILE \t The config file to use (default = '%s'). \n " \
" -D, --pidfile PIDFILE \t The path of the PID file (default = '%s'). \n " \
" -d, --daemonize \t Enables daemonization of the process (default = disabled). \n " \
" -l, --syslog \t \t Enables dumping of CDRs to syslog (default = disabled). \n " \
" -i, --interval INT \t The creation interval (default = %d). \n " \
" -h, --med-host HOST \t The ACC db host (default = '%s'). \n " \
" -o, --med-port PORT \t The ACC db port (default = '%d'). \n " \
" -u, --med-user USER \t The ACC db user (default = '%s'). \n " \
" -p, --med-pass PASS \t The ACC db pass (default = '%s'). \n " \
" -b, --med-db DB \t The ACC db name (default = '%s'). \n " \
" -H, --cdr-host HOST \t The CDR db host (default = '%s'). \n " \
" -O, --cdr-port PORT \t The CDR db port (default = '%d'). \n " \
" -U, --cdr-user USER \t The CDR db user (default = '%s'). \n " \
" -P, --cdr-pass PASS \t The CDR db pass (default = '%s'). \n " \
" -B, --cdr-db DB \t The CDR db name (default = '%s'). \n " \
" -S, --prov-host HOST \t The prov db host (default = '%s'). \n " \
" -T, --prov-port PORT \t The prov db port (default = '%d'). \n " \
" -R, --prov-user USER \t The prov db user (default = '%s'). \n " \
" -A, --prov-pass PASS \t The prov db pass (default = '%s'). \n " \
" -N, --prov-db DB \t The prov db name (default = '%s'). \n " \
" -Z, --stats-host HOST \t The stats db host (default = '%s'). \n " \
" -z, --stats-port PORT \t The stats db port (default = '%d'). \n " \
" -W, --stats-user USER \t The stats db user (default = '%s'). \n " \
" -w, --stats-pass PASS \t The stats db pass (default = '%s'). \n " \
" -X, --stats-db DB \t The stats db name (default = '%s'). \n " \
" -x, --stats-period INT \t The stats db period (default = '%d', 1=hour, 2=day, 3=month). \n " \
" -m, --maintenance \t Maintenance mode (do nothing, just sleep). \n " \
" -s, --leg-tokens \t Strict acc fields (move to trash otherwise). \n " \
" -?, --help \t \t Displays this message. \n " ,
MEDIATOR_VERSION , self , MEDIATOR_DEFAULT_CONFIG_FILE ,
MEDIATOR_DEFAULT_PIDPATH , MEDIATOR_DEFAULT_INTERVAL ,
MEDIATOR_DEFAULT_ACCHOST , MEDIATOR_DEFAULT_ACCPORT ,
MEDIATOR_DEFAULT_ACCUSER , MEDIATOR_DEFAULT_ACCPASS ,
@ -86,82 +157,110 @@ static void config_help(const char *self, int rc)
exit ( rc ) ;
}
static void config_set_string_option ( char * * str , char * opt )
static void config_set_string_option ( char * * str , const char * opt )
{
free ( * str ) ;
* str = strdup ( opt ) ;
}
static void config_set_string_default ( char * * str , char * def )
static void config_set_string_default ( char * * str , const char * def )
{
if ( * str = = NULL )
* str = strdup ( def ) ;
}
int config_parse_cmdopts ( int argc , char * * argv )
static void config_set_option ( enum config_option option , const char * value )
{
int c ;
while ( ( c = getopt ( argc , argv , " D:i:dl?h:u:p:b:o:H:U:P:B:O:S:T:R:A:N:Z:z:W:w:X:x:ms " ) ) ! = - 1 )
{
if ( c = = ' ? ' | | c = = ' : ' )
config_help ( argv [ 0 ] , 0 ) ;
else if ( c = = ' d ' )
config_daemonize = 1 ;
else if ( c = = ' l ' )
config_dumpcdr = 1 ;
else if ( c = = ' D ' )
config_set_string_option ( & config_pid_path , optarg ) ;
else if ( c = = ' i ' )
config_interval = atoi ( optarg ) ;
else if ( c = = ' h ' )
config_set_string_option ( & config_med_host , optarg ) ;
else if ( c = = ' u ' )
config_set_string_option ( & config_med_user , optarg ) ;
else if ( c = = ' p ' )
config_set_string_option ( & config_med_pass , optarg ) ;
else if ( c = = ' b ' )
config_set_string_option ( & config_med_db , optarg ) ;
else if ( c = = ' o ' )
config_med_port = atoi ( optarg ) ;
else if ( c = = ' H ' )
config_set_string_option ( & config_cdr_host , optarg ) ;
else if ( c = = ' U ' )
config_set_string_option ( & config_cdr_user , optarg ) ;
else if ( c = = ' P ' )
config_set_string_option ( & config_cdr_pass , optarg ) ;
else if ( c = = ' B ' )
config_set_string_option ( & config_cdr_db , optarg ) ;
else if ( c = = ' O ' )
config_cdr_port = atoi ( optarg ) ;
else if ( c = = ' S ' )
config_set_string_option ( & config_prov_host , optarg ) ;
else if ( c = = ' R ' )
config_set_string_option ( & config_prov_user , optarg ) ;
else if ( c = = ' A ' )
config_set_string_option ( & config_prov_pass , optarg ) ;
else if ( c = = ' N ' )
config_set_string_option ( & config_prov_db , optarg ) ;
else if ( c = = ' T ' )
config_prov_port = atoi ( optarg ) ;
else if ( c = = ' Z ' )
config_set_string_option ( & config_stats_host , optarg ) ;
else if ( c = = ' z ' )
config_stats_port = atoi ( optarg ) ;
else if ( c = = ' W ' )
config_set_string_option ( & config_stats_user , optarg ) ;
else if ( c = = ' w ' )
config_set_string_option ( & config_stats_pass , optarg ) ;
else if ( c = = ' X ' )
config_set_string_option ( & config_stats_db , optarg ) ;
else if ( c = = ' x ' )
config_stats_period = ( med_stats_period_t ) atoi ( optarg ) ;
else if ( c = = ' m ' )
config_maintenance = 1 ;
else if ( c = = ' s ' )
strict_leg_tokens = 1 ;
switch ( option ) {
case OPT_DAEMONIZE :
config_daemonize = 1 ;
break ;
case OPT_SYSLOG :
config_dumpcdr = 1 ;
break ;
case OPT_CONFIGFILE :
config_set_string_option ( & config_file_path , value ) ;
break ;
case OPT_PIDFILE :
config_set_string_option ( & config_pid_path , value ) ;
break ;
case OPT_INTERVAL :
config_interval = atoi ( value ) ;
break ;
case OPT_MED_HOST :
config_set_string_option ( & config_med_host , value ) ;
break ;
case OPT_MED_USER :
config_set_string_option ( & config_med_user , value ) ;
break ;
case OPT_MED_PASS :
config_set_string_option ( & config_med_pass , value ) ;
break ;
case OPT_MED_DB :
config_set_string_option ( & config_med_db , value ) ;
break ;
case OPT_MED_PORT :
config_med_port = atoi ( value ) ;
break ;
case OPT_CDR_HOST :
config_set_string_option ( & config_cdr_host , value ) ;
break ;
case OPT_CDR_USER :
config_set_string_option ( & config_cdr_user , value ) ;
break ;
case OPT_CDR_PASS :
config_set_string_option ( & config_cdr_pass , value ) ;
break ;
case OPT_CDR_DB :
config_set_string_option ( & config_cdr_db , value ) ;
break ;
case OPT_CDR_PORT :
config_cdr_port = atoi ( value ) ;
break ;
case OPT_PROV_HOST :
config_set_string_option ( & config_prov_host , value ) ;
break ;
case OPT_PROV_USER :
config_set_string_option ( & config_prov_user , value ) ;
break ;
case OPT_PROV_PASS :
config_set_string_option ( & config_prov_pass , value ) ;
break ;
case OPT_PROV_DB :
config_set_string_option ( & config_prov_db , value ) ;
break ;
case OPT_PROV_PORT :
config_prov_port = atoi ( value ) ;
break ;
case OPT_STATS_HOST :
config_set_string_option ( & config_stats_host , value ) ;
break ;
case OPT_STATS_USER :
config_set_string_option ( & config_stats_user , value ) ;
break ;
case OPT_STATS_PASS :
config_set_string_option ( & config_stats_pass , value ) ;
break ;
case OPT_STATS_PORT :
config_stats_port = atoi ( value ) ;
break ;
case OPT_STATS_DB :
config_set_string_option ( & config_stats_db , value ) ;
break ;
case OPT_STATS_PERIOD :
config_stats_period = ( med_stats_period_t ) atoi ( value ) ;
break ;
case OPT_MAINTENANCE :
config_maintenance = 1 ;
break ;
case OPT_LEG_TOKENS :
strict_leg_tokens = 1 ;
break ;
}
}
static void config_set_defaults ( void )
{
/* Set defaults for string values. */
config_set_string_default ( & config_pid_path , MEDIATOR_DEFAULT_PIDPATH ) ;
config_set_string_default ( & config_med_host , MEDIATOR_DEFAULT_ACCHOST ) ;
@ -180,10 +279,111 @@ int config_parse_cmdopts(int argc, char **argv)
config_set_string_default ( & config_stats_user , MEDIATOR_DEFAULT_STATSUSER ) ;
config_set_string_default ( & config_stats_pass , MEDIATOR_DEFAULT_STATSPASS ) ;
config_set_string_default ( & config_stats_db , MEDIATOR_DEFAULT_STATSDB ) ;
}
static int config_parse_line ( char * line )
{
char * sep = line ;
const char * value ;
struct option * option ;
for ( sep = line ; * sep ; sep + + )
if ( isspace ( * sep ) | | * sep = = ' = ' )
break ;
for ( value = sep ; * value ; value + + )
if ( ! isspace ( * value ) & & * value ! = ' = ' )
break ;
if ( value ! = sep )
* sep = ' \0 ' ;
for ( option = long_options ; option - > name ; option + + )
if ( strcmp ( option - > name , line ) = = 0 )
break ;
if ( option - > name = = NULL ) {
syslog ( LOG_ERR , " No option found in config file line '%s' " , line ) ;
return - 1 ;
}
if ( option - > has_arg = = no_argument & & * value ! = ' \0 ' ) {
syslog ( LOG_ERR , " Unexpected value in config file option '%s' " ,
option - > name ) ;
return - 1 ;
} else if ( option - > has_arg = = required_argument & & * value = = ' \0 ' ) {
syslog ( LOG_ERR , " Missing value in config file option '%s' " ,
option - > name ) ;
return - 1 ;
}
config_set_option ( option - > val , value ) ;
return 0 ;
}
static int config_parse_file ( const char * filename )
{
FILE * conffile ;
char * line = NULL ;
size_t len = 0 ;
ssize_t nread ;
syslog ( LOG_DEBUG , " Loading config file '%s' " , filename ) ;
conffile = fopen ( filename , " r " ) ;
if ( conffile = = NULL ) {
if ( errno = = ENOENT )
return 0 ;
syslog ( LOG_ERR , " Error loading config file: %s " , strerror ( errno ) ) ;
return - 1 ;
}
while ( ( nread = getline ( & line , & len , conffile ) ) > = 0 ) {
if ( line [ 0 ] = = ' # ' )
continue ;
if ( line [ nread - 1 ] = = ' \n ' )
line [ nread - 1 ] = ' \0 ' ;
if ( config_parse_line ( line ) < 0 ) {
syslog ( LOG_ERR , " Error parsing config file " ) ;
return - 1 ;
}
}
free ( line ) ;
fclose ( conffile ) ;
return 0 ;
}
static int config_parse_cmdopts ( int argc , char * * argv )
{
int c ;
while ( ( c = getopt_long ( argc , argv , options , long_options , NULL ) ) ! = - 1 )
{
if ( c = = ' ? ' | | c = = ' : ' )
config_help ( argv [ 0 ] , 0 ) ;
else
config_set_option ( c , optarg ) ;
}
return 0 ;
}
int config_parse ( int argc , char * * argv )
{
int rc = 0 ;
rc | = config_parse_cmdopts ( argc , argv ) ;
config_set_string_default ( & config_file_path , MEDIATOR_DEFAULT_CONFIG_FILE ) ;
rc | = config_parse_file ( config_file_path ) ;
config_set_defaults ( ) ;
return rc ;
}
void config_cleanup ( )
{
free ( config_pid_path ) ;