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

490 lines
17 KiB

#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;
char *config_pid_path;
char *config_med_host;
char *config_med_user;
char *config_med_pass;
char *config_med_db;
unsigned int config_med_port = MEDIATOR_DEFAULT_ACCPORT;
char *config_redis_host;
unsigned int config_redis_port = MEDIATOR_DEFAULT_REDISPORT;
unsigned int config_redis_db = MEDIATOR_DEFAULT_REDISDB;
char *config_redis_pass = NULL;
char *config_cdr_host;
char *config_cdr_user;
char *config_cdr_pass;
char *config_cdr_db;
unsigned int config_cdr_port = MEDIATOR_DEFAULT_CDRPORT;
char *config_intermediate_cdr_host;
unsigned int config_intermediate_cdr_port = MEDIATOR_DEFAULT_CDRPORT;
char *config_cdr_error_file;
char *config_prov_host;
char *config_prov_user;
char *config_prov_pass;
char *config_prov_db;
unsigned int config_prov_port = MEDIATOR_DEFAULT_PROVPORT;
char *config_stats_host;
char *config_stats_user;
char *config_stats_pass;
char *config_stats_db;
unsigned int config_stats_port = MEDIATOR_DEFAULT_STATSPORT;
med_stats_period_t config_stats_period = MEDIATOR_DEFAULT_STATSPERIOD;
int config_maintenance = 0;
int strict_leg_tokens = 0;
int config_max_acc_age = 0;
int config_intermediate_interval = 0;
med_loglevel_t config_loglevel = MEDIATOR_DEFAULT_LOGLEVEL;
enum config_option {
OPT_CONFIGFILE = 'c',
OPT_DAEMONIZE = 'd',
OPT_PIDFILE = 'D',
OPT_SYSLOG = 'l',
OPT_LOGLEVEL = '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_INTERMEDIATE_CDR_HOST = 'y',
OPT_INTERMEDIATE_CDR_PORT = 'Y',
OPT_CDR_ERROR_FILE = 'E',
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_REDIS_HOST = 'a',
OPT_REDIS_PORT = 't',
OPT_REDIS_DB = 'r',
OPT_REDIS_PASS = 'e',
OPT_STATS_PERIOD = 'x',
OPT_MAINTENANCE = 'm',
OPT_LEG_TOKENS = 's',
OPT_MAX_ACC_AGE = 'M',
OPT_INTERMEDIATE_INTERVAL = 'I',
};
static const char options[] = "?a:c:e:D:i:dlL:h:u:p:b:o:H:U:P:B:O:S:t:T:r:R:A:N:Z:z:W:w:X:x:msM:I:y:Y:";
struct option long_options[] = {
{ "configfile", required_argument, NULL, OPT_CONFIGFILE },
{ "pidfile", required_argument, NULL, OPT_PIDFILE },
{ "daemonize", no_argument, NULL, OPT_DAEMONIZE },
{ "logquery", no_argument, NULL, OPT_SYSLOG },
{ "loglevel", required_argument, NULL, OPT_LOGLEVEL },
{ "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 },
{ "intermediate-cdr-host", required_argument, NULL, OPT_INTERMEDIATE_CDR_HOST },
{ "intermediate-cdr-port", required_argument, NULL, OPT_INTERMEDIATE_CDR_PORT },
{ "cdr-error-file", required_argument, NULL, OPT_CDR_ERROR_FILE },
{ "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 },
{ "redis-host", required_argument, NULL, OPT_REDIS_HOST },
{ "redis-port", required_argument, NULL, OPT_REDIS_PORT },
{ "redis-db", required_argument, NULL, OPT_REDIS_DB },
{ "redis-pass", required_argument, NULL, OPT_REDIS_PASS },
{ "stats-period", required_argument, NULL, OPT_STATS_PERIOD },
{ "maintenance", no_argument, NULL, OPT_MAINTENANCE },
{ "leg-tokens", no_argument, NULL, OPT_LEG_TOKENS },
{ "max-acc-age", required_argument, NULL, OPT_MAX_ACC_AGE },
{ "intermediate-interval", required_argument, NULL, OPT_INTERMEDIATE_INTERVAL },
{ 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 [<option>...]\n" \
"\n" \
"Options:\n" \
" -c, --configfile FILE\tThe config file to use (default = '%s').\n" \
" -D, --pidfile PIDFILE\tThe path of the PID file (default = '%s').\n" \
" -d, --daemonize\tEnables daemonization of the process (default = disabled).\n" \
" -l, --logquery\t\tEnables logging of CDR sql query to file (default = disabled).\n" \
" -L, --loglevel\tThe loglevel from 7=debug to 0=emergency (default = %d).\n" \
" -i, --interval INT\tThe creation interval (default = %d).\n" \
" -h, --med-host HOST\tThe ACC db host (default = '%s').\n" \
" -o, --med-port PORT\tThe ACC db port (default = '%d').\n" \
" -u, --med-user USER\tThe ACC db user (default = '%s').\n" \
" -p, --med-pass PASS\tThe ACC db pass (default = '%s').\n" \
" -b, --med-db DB\tThe ACC db name (default = '%s').\n" \
" -H, --cdr-host HOST\tThe CDR db host (default = '%s').\n" \
" -O, --cdr-port PORT\tThe CDR db port (default = '%d').\n" \
" -U, --cdr-user USER\tThe CDR db user (default = '%s').\n" \
" -P, --cdr-pass PASS\tThe CDR db pass (default = '%s').\n" \
" -B, --cdr-db DB\tThe CDR db name (default = '%s').\n" \
" -y, --intermediate-cdr-host HOST\tThe CDR db host (default = '%s').\n" \
" -Y, --intermediate-cdr-port PORT\tThe CDR db port (default = '%d').\n" \
" -E, --cdr-error-file FILE\tThe CDR db port (default = none).\n" \
" -S, --prov-host HOST\tThe prov db host (default = '%s').\n" \
" -T, --prov-port PORT\tThe prov db port (default = '%d').\n" \
" -R, --prov-user USER\tThe prov db user (default = '%s').\n" \
" -A, --prov-pass PASS\tThe prov db pass (default = '%s').\n" \
" -N, --prov-db DB\tThe prov db name (default = '%s').\n" \
" -Z, --stats-host HOST\tThe stats db host (default = '%s').\n" \
" -z, --stats-port PORT\tThe stats db port (default = '%d').\n" \
" -W, --stats-user USER\tThe stats db user (default = '%s').\n" \
" -w, --stats-pass PASS\tThe stats db pass (default = '%s').\n" \
" -X, --stats-db DB\tThe stats db name (default = '%s').\n" \
" -x, --stats-period INT\tThe stats db period (default = '%d', 1=hour, 2=day, 3=month).\n" \
" -a, --redis-host HOST\tThe redis db host (default = '%s').\n" \
" -t, --redis-port PORT\tThe redis db port (default = '%d').\n" \
" -e, --redis-pass PASS\tThe redis db pass (default = none).\n" \
" -r, --redis-db DB\tThe redis usrloc db number (default = '%d').\n" \
" -m, --maintenance\tMaintenance mode (do nothing, just sleep).\n" \
" -s, --leg-tokens\tStrict acc fields (move to trash otherwise).\n" \
" -M, --max-acc-age\tMaximum age of acc records before trashing them (default = disabled).\n" \
" -I, --intermediate-interval\tHow often to write/update intermediate CDRs (default = disabled).\n" \
" -?, --help\t\tDisplays this message.\n",
MEDIATOR_VERSION, self, MEDIATOR_DEFAULT_CONFIG_FILE,
MEDIATOR_DEFAULT_PIDPATH, MEDIATOR_DEFAULT_LOGLEVEL,
MEDIATOR_DEFAULT_INTERVAL,
MEDIATOR_DEFAULT_ACCHOST, MEDIATOR_DEFAULT_ACCPORT,
MEDIATOR_DEFAULT_ACCUSER, MEDIATOR_DEFAULT_ACCPASS,
MEDIATOR_DEFAULT_ACCDB,
MEDIATOR_DEFAULT_CDRHOST, MEDIATOR_DEFAULT_CDRPORT,
MEDIATOR_DEFAULT_CDRUSER, MEDIATOR_DEFAULT_CDRPASS,
MEDIATOR_DEFAULT_CDRDB,
MEDIATOR_DEFAULT_CDRHOST, MEDIATOR_DEFAULT_CDRPORT,
MEDIATOR_DEFAULT_PROVHOST, MEDIATOR_DEFAULT_PROVPORT,
MEDIATOR_DEFAULT_PROVUSER, MEDIATOR_DEFAULT_PROVPASS,
MEDIATOR_DEFAULT_PROVDB,
MEDIATOR_DEFAULT_STATSHOST, MEDIATOR_DEFAULT_STATSPORT,
MEDIATOR_DEFAULT_STATSUSER, MEDIATOR_DEFAULT_STATSPASS,
MEDIATOR_DEFAULT_STATSDB, MEDIATOR_DEFAULT_STATSPERIOD,
MEDIATOR_DEFAULT_REDISHOST, MEDIATOR_DEFAULT_REDISPORT,
MEDIATOR_DEFAULT_REDISDB);
exit(rc);
}
static void config_set_string_option(char **str, const char *opt)
{
free(*str);
*str = strdup(opt);
}
static void config_set_string_default(char **str, const char *def)
{
if (*str == NULL)
*str = strdup(def);
}
static void config_set_option(enum config_option option, const char *value)
{
switch (option) {
case OPT_DAEMONIZE:
config_daemonize = 1;
break;
case OPT_SYSLOG:
config_dumpcdr = 1;
break;
case OPT_LOGLEVEL:
config_loglevel = atoi(value);
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_INTERMEDIATE_CDR_HOST:
config_set_string_option(&config_intermediate_cdr_host, value);
break;
case OPT_INTERMEDIATE_CDR_PORT:
config_intermediate_cdr_port = atoi(value);
break;
case OPT_CDR_ERROR_FILE:
config_set_string_option(&config_cdr_error_file, 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_REDIS_HOST:
config_set_string_option(&config_redis_host, value);
break;
case OPT_REDIS_PORT:
config_redis_port = atoi(value);
break;
case OPT_REDIS_DB:
config_redis_db = atoi(value);
break;
case OPT_REDIS_PASS:
config_set_string_option(&config_redis_pass, value);
break;
case OPT_MAINTENANCE:
config_maintenance = 1;
break;
case OPT_LEG_TOKENS:
strict_leg_tokens = 1;
break;
case OPT_MAX_ACC_AGE:
config_max_acc_age = atoi(value);
break;
case OPT_INTERMEDIATE_INTERVAL:
config_intermediate_interval = atoi(value);
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);
config_set_string_default(&config_med_user, MEDIATOR_DEFAULT_ACCUSER);
config_set_string_default(&config_med_pass, MEDIATOR_DEFAULT_ACCPASS);
config_set_string_default(&config_med_db, MEDIATOR_DEFAULT_ACCDB);
config_set_string_default(&config_cdr_host, MEDIATOR_DEFAULT_CDRHOST);
config_set_string_default(&config_cdr_user, MEDIATOR_DEFAULT_CDRUSER);
config_set_string_default(&config_cdr_pass, MEDIATOR_DEFAULT_CDRPASS);
config_set_string_default(&config_cdr_db, MEDIATOR_DEFAULT_CDRDB);
config_set_string_default(&config_intermediate_cdr_host, MEDIATOR_DEFAULT_CDRHOST);
config_set_string_default(&config_prov_host, MEDIATOR_DEFAULT_PROVHOST);
config_set_string_default(&config_prov_user, MEDIATOR_DEFAULT_PROVUSER);
config_set_string_default(&config_prov_pass, MEDIATOR_DEFAULT_PROVPASS);
config_set_string_default(&config_prov_db, MEDIATOR_DEFAULT_PROVDB);
config_set_string_default(&config_stats_host, MEDIATOR_DEFAULT_STATSHOST);
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);
config_set_string_default(&config_redis_host, MEDIATOR_DEFAULT_REDISHOST);
}
static int config_parse_line(char *line)
{
char *sep;
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) {
L_ERROR("No option found in config file line '%s'", line);
return -1;
}
if (option->has_arg == no_argument && *value != '\0') {
L_ERROR("Unexpected value in config file option '%s'",
option->name);
return -1;
} else if (option->has_arg == required_argument && *value == '\0') {
L_ERROR("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;
L_DEBUG("Loading config file '%s'", filename);
conffile = fopen(filename, "r");
if (conffile == NULL) {
if (errno == ENOENT)
return 0;
L_ERROR("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) {
L_ERROR("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);
free(config_cdr_host);
free(config_cdr_user);
free(config_cdr_pass);
free(config_cdr_db);
free(config_intermediate_cdr_host);
free(config_cdr_error_file);
free(config_med_host);
free(config_med_user);
free(config_med_pass);
free(config_med_db);
free(config_prov_host);
free(config_prov_user);
free(config_prov_pass);
free(config_prov_db);
free(config_stats_host);
free(config_stats_user);
free(config_stats_pass);
free(config_stats_db);
free(config_redis_host);
if (config_redis_pass)
free(config_redis_pass);
}