/*-
* Copyright (c) 2004 Free (Olivier Beyssac)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 AUTHOR 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.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <syslog.h>
#include "utils.h"
#include "options.h"
#define CONFIG_BUFSIZE (1024)
extern struct options opt;
/* Append a host to the notify_hosts list */
static int notify_hosts_append(int index, char *value)
{
char *c, svc;
size_t svl, len;
len = sizeof(char *) * ((index + 1) * 2 + 1);
if ((opt.notify_hosts = realloc(opt.notify_hosts, len)) == NULL) {
if (opt.syslog)
syslog(LOG_ERR, "%s: unable to calloc %d bytes to split host\n",
opt.progname, sizeof(char *) * 3);
else
fprintf(stderr, "%s: unable to calloc %d bytes to split host\n",
opt.progname, sizeof(char *) * 3);
return 0;
}
opt.notify_hosts[index * 2 + 2] = NULL;
if ((c = strchr(value, ':')) == NULL) {
opt.notify_hosts[index*2] = value;
opt.notify_hosts[index*2+1] = "2905";
} else {
savebufpos(svc, svl, value, strlen(value) - strlen(c));
if ((opt.notify_hosts[index*2] = strdup(value)) == NULL) {
if (opt.syslog)
syslog(LOG_ERR, "%s: strdup failed\n", opt.progname);
else
fprintf(stderr, "%s: strdup failed\n", opt.progname);
return 0;
}
restorebuf(svc, svl, value);
if ((opt.notify_hosts[index*2+1] = strdup(c + 1)) == NULL) {
if (opt.syslog)
syslog(LOG_ERR, "%s: strdup failed\n", opt.progname);
else
fprintf(stderr, "%s: strdup failed\n", opt.progname);
return 0;
}
}
return 1;
}
/* Read comma separated hosts list and fill relevant structure */
static int read_hosts_list(char *value)
{
char *c, *p;
int i = 0;
p = c = value;
while ((c = strchr(c, ','))) {
*c = '\0';
for (c++; *c == ',' || *c == ' ' || *c == '\t'; c++)
notify_hosts_append(i++, p);
p = c;
}
notify_hosts_append(i++, p);
return 1;
}
/* Set option structure given variable name and its value */
static int set_option(const char *variable, char *value)
{
if (!strcmp(variable, "daemon")) {
opt.daemon = xstrtol(value);
return options_check(DAEMON_CHK, opt.daemon);
}
if (!strcmp(variable, "max_submissions")) {
opt.max_req = xstrtol(value);
return options_check(MAX_REQ_CHK, opt.max_req);
}
if (!strcmp(variable, "min_interval")) {
opt.interval = xstrtol(value);
return options_check(INTERVAL_CHK, opt.interval);
}
if (!strcmp(variable, "ip_list_size")) {
opt.list_size = xstrtol(value);
return options_check(LIST_SIZE_CHK, opt.list_size);
}
if (!strcmp(variable, "blacklist_size")) {
opt.blacklist_size = xstrtol(value);
return options_check(BLACKLIST_SIZE_CHK, opt.blacklist_size);
}
if (!strcmp(variable, "blacklist_expiration")) {
opt.blacklist_expiration = xstrtol(value);
return options_check(BLACKLIST_EXPIRATION_CHK, opt.blacklist_expiration);
}
if (!strcmp(variable, "client_timeout")) {
opt.client_timeout = xstrtol(value);
return options_check(CLIENT_TIMEOUT_CHK, opt.client_timeout);
}
if (!strcmp(variable, "address"))
opt.listening_ip = value;
else if (!strcmp(variable, "port"))
opt.port = value;
else if (!strcmp(variable, "log_level"))
opt.log_level = xstrtol(value);
else if (!strcmp(variable, "user"))
opt.uid = value;
else if (!strcmp(variable, "group"))
opt.gid = value;
else if (!strcmp(variable, "iplist_dump"))
opt.wl_filename = value;
else if (!strcmp(variable, "blacklist_dump"))
opt.bl_filename = value;
else if (!strcmp(variable, "pid_filename"))
opt.pid_filename = value;
else if (!strcmp(variable, "acl_filename"))
opt.acl_filename = value;
else if (!strcmp(variable, "whitelist_filename"))
opt.whitelist_filename = value;
else if (!strcmp(variable, "notifies_to"))
return read_hosts_list(value);
else return 0;
return 1;
}
/* Open the config file and parse it. Return 0 on error */
extern int parse_config(void)
{
FILE *fd;
char buf[CONFIG_BUFSIZE];
char *variable;
char *value;
size_t i, end, len;
int lineno = 0;
char svc;
int svl;
if ((fd = fopen(opt.config_file, "r")) == NULL) {
if (errno == ENOENT)
return 1;
if (opt.syslog)
syslog(LOG_ERR, "%s: error while opening %s\n",
opt.progname, opt.config_file);
else
fprintf(stderr, "%s: error while opening %s\n",
opt.progname, opt.config_file);
perror("fopen");
return 0;
}
while (fgets(buf, CONFIG_BUFSIZE, fd)) {
lineno++;
len = strlen(buf);
if (buf[0] == '#' || buf[0] == '\n')
continue;
variable = NULL;
value = NULL;
/* Search for '=' */
for (i = 1; i < len && buf[i] != '='; i++);
if (i >= len - 2) {
if (opt.syslog)
syslog(LOG_ERR, "%s:%s:%i: invalid line: %s",
opt.progname, opt.config_file, lineno, buf);
else
fprintf(stderr, "%s:%s:%i: invalid line: %s",
opt.progname, opt.config_file, lineno, buf);
return 0;
}
/* Go back to the real end of the variable and copy it */
end = i - 1;
while (buf[end] == ' ' || buf[end] == '\t')
end--;
variable = buf;
savebufpos(svc, svl, buf, end + 1);
buf[end+1] = '\0';
/* Get the value now */
for (i++; i < len && (buf[i] == ' ' || buf[i] == '\t'); i++);
for (end = len - 1; end > i && (buf[end] == ' ' || buf[end] == '\t'
|| buf[end] == '\n' || buf[end] == '\r');
end--);
if ((value = xstrndup(buf + i, end - i + 1)) == NULL) {
if (opt.syslog)
syslog(LOG_ERR, "%s: parse_config failed to alloc %d bytes",
opt.progname, end - i);
else
fprintf(stderr, "%s: parse_config failed to alloc %d bytes",
opt.progname, end - i);
return 0;
}
if (!set_option(variable, value)) {
restorebuf(svc, svl, buf);
if (opt.syslog)
syslog(LOG_ERR, "%s: invalid line in config file %s:%d\n%s",
opt.progname, opt.config_file, lineno, buf);
else
fprintf(stderr, "%s: invalid line in config file %s:%d\n%s",
opt.progname, opt.config_file, lineno, buf);
return 0;
}
}
fclose(fd);
return 1;
}
syntax highlighted by Code2HTML, v. 0.9.1