/* Copyright (C) 2002-2005 Thomas Ries This file is part of Siproxd. Siproxd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Siproxd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Siproxd; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "config.h" #include #include #include #include #include #include #include #include "siproxd.h" #include "log.h" static char const ident[]="$Id$"; /* configuration storage */ extern struct siproxd_config configuration; /* prototypes used locally only */ static int parse_config (FILE *configfile); /* try to open (whichever is found first): * * $HOME/.rc * /etc/.conf * /usr/etc/.conf * /usr/local/etc/.conf * * RETURNS * STS_SUCCESS on success * STS_FAILURE on error */ int read_config(char *name, int search) { int sts; FILE *configfile=NULL; int i; char tmp[256]; const char *completion[] = { "%s/.%src", /* this one is special... (idx=0)*/ SIPROXDCONFPATH "/%s.conf", "/etc/%s.conf", "/usr/etc/%s.conf", "/usr/local/etc/%s.conf", NULL }; DEBUGC(DBCLASS_CONFIG,"trying to read config file"); /* shall I search the config file myself ? */ if (search != 0) { /* yup, try to find it */ for (i=0; completion[i]!=NULL; i++) { switch (i) { case 0: sprintf(tmp,completion[i],getenv("HOME"),name); break; default: sprintf(tmp,completion[i],name); break; } DEBUGC(DBCLASS_CONFIG,"... trying %s",tmp); configfile = fopen(tmp,"r"); if (configfile==NULL) continue; break; /* got config file */ } } else { /* don't search it, just try the one given file */ DEBUGC(DBCLASS_CONFIG,"... trying %s",name); configfile = fopen(name,"r"); } /* config file not found or unable to open for read */ if (configfile==NULL) { ERROR ("could not open config file: %s", strerror(errno)); return STS_FAILURE; } sts = parse_config(configfile); fclose(configfile); /* * Post-process configuration variables that have conditions that * must be met; warn if we have to adjust any. */ if (configuration.rtp_port_low & 0x01) { /* rtp_port_low must be an even number... */ configuration.rtp_port_low = (configuration.rtp_port_low + 1) & ~0x01; WARN("rtp_port_low should be an even number; it's been rounded up to %i", configuration.rtp_port_low); } if (configuration.rtp_port_high & 0x01) { /* rtp_high_port should be either the top RTP port allowed, */ /* or the top RTCP port allowed. If the latter, then reset */ /* to the former... Don't need a warning here. It's okay. */ configuration.rtp_port_high = configuration.rtp_port_high & ~0x01; DEBUGC(DBCLASS_CONFIG, "rounded rtp_port_high down to %i", configuration.rtp_port_high); } return sts; } /* * parse configuration file * * RETURNS * STS_SUCCESS on success * STS_FAILURE on error */ static int parse_config (FILE *configfile) { char buff[1024]; char *ptr; int i; int k; int num; char *tmpptr; struct cfgopts { char *keyword; enum type {TYP_INT4, TYP_STRING, TYP_FLOAT, TYP_STRINGA} type; void *dest; } configoptions[] = { { "debug_level", TYP_INT4, &configuration.debuglevel }, { "debug_port", TYP_INT4, &configuration.debugport }, { "sip_listen_port", TYP_INT4, &configuration.sip_listen_port }, { "daemonize", TYP_INT4, &configuration.daemonize }, { "silence_log", TYP_INT4, &configuration.silence_log }, { "if_inbound", TYP_STRING, &configuration.inbound_if }, { "if_outbound", TYP_STRING, &configuration.outbound_if }, { "host_outbound", TYP_STRING, &configuration.outbound_host }, { "rtp_port_low", TYP_INT4, &configuration.rtp_port_low }, { "rtp_port_high", TYP_INT4, &configuration.rtp_port_high }, { "rtp_timeout", TYP_INT4, &configuration.rtp_timeout }, { "rtp_proxy_enable", TYP_INT4, &configuration.rtp_proxy_enable }, { "user", TYP_STRING, &configuration.user }, { "chrootjail", TYP_STRING, &configuration.chrootjail }, { "hosts_allow_reg", TYP_STRING, &configuration.hosts_allow_reg }, { "hosts_allow_sip", TYP_STRING, &configuration.hosts_allow_sip }, { "hosts_deny_sip", TYP_STRING, &configuration.hosts_deny_sip }, { "hosts_deny_sip", TYP_STRING, &configuration.hosts_deny_sip }, { "proxy_auth_realm", TYP_STRING, &configuration.proxy_auth_realm }, { "proxy_auth_passwd", TYP_STRING, &configuration.proxy_auth_passwd }, { "proxy_auth_pwfile", TYP_STRING, &configuration.proxy_auth_pwfile }, { "mask_host", TYP_STRINGA,&configuration.mask_host }, { "masked_host", TYP_STRINGA,&configuration.masked_host }, { "outbound_proxy_host", TYP_STRING, &configuration.outbound_proxy_host }, { "outbound_proxy_port", TYP_INT4, &configuration.outbound_proxy_port }, { "outbound_domain_name",TYP_STRINGA,&configuration.outbound_proxy_domain_name }, { "outbound_domain_host",TYP_STRINGA,&configuration.outbound_proxy_domain_host }, { "outbound_domain_port",TYP_STRINGA,&configuration.outbound_proxy_domain_port }, { "registration_file", TYP_STRING, &configuration.registrationfile }, { "log_calls", TYP_INT4, &configuration.log_calls }, { "pid_file", TYP_STRING, &configuration.pid_file }, { "default_expires", TYP_INT4, &configuration.default_expires }, { "autosave_registrations",TYP_INT4, &configuration.autosave_registrations }, {0, 0, 0} }; while (fgets(buff,sizeof(buff),configfile) != NULL) { /* life insurance */ buff[sizeof(buff)-1]='\0'; /* strip New line & CR if present */ for (i=1; i<=2; i++) { if ((buff[strlen(buff)-i]=='\n') || (buff[strlen(buff)-i]=='\r')) { buff[strlen(buff)-i]='\0'; } } /* strip emtpy lines */ if (strlen(buff) == 0) continue; /* strip comments and line with only whitespaces */ for (i=0;i