/*- * 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 #include #include #include #include #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; }