Revert "Revert "and added files""
[bcm963xx.git] / userapps / opensource / siproxd / src / readconf.c
diff --git a/userapps/opensource/siproxd/src/readconf.c b/userapps/opensource/siproxd/src/readconf.c
new file mode 100755 (executable)
index 0000000..71c99b1
--- /dev/null
@@ -0,0 +1,310 @@
+/*
+    Copyright (C) 2002-2005  Thomas Ries <tries@gmx.net>
+
+    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 <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+
+#include <osipparser2/osip_parser.h>
+
+#include "siproxd.h"
+#include "log.h"
+
+static char const ident[]="$Id: readconf.c,v 1.30 2005/01/08 10:05:12 hb9xar Exp $";
+
+/* configuration storage */
+extern struct siproxd_config configuration;
+
+/* prototypes used locally only */
+static int parse_config (FILE *configfile);
+
+
+/* try to open (whichever is found first):
+ *     <name>
+ *     $HOME/.<name>rc
+ *     /etc/<name>.conf
+ *     /usr/etc/<name>.conf
+ *     /usr/local/etc/<name>.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 },
+      { "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 },
+      {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<strlen(buff);i++) {
+         if ((buff[i] == ' ') || (buff[i] == '\t')) continue;
+         if (buff[i] =='#') i=strlen(buff);
+         break;
+      }
+      if (i == strlen(buff)) continue;
+
+      DEBUGC(DBCLASS_CONFIG,"pc:\"%s\"",buff);
+
+      /* scan for known keyword */
+      for (k=0; configoptions[k].keyword != NULL; k++) {
+         if ((ptr=strstr(buff, configoptions[k].keyword)) != NULL) {
+            ptr += strlen(configoptions[k].keyword);
+            DEBUGC(DBCLASS_CONFIG,"got keyword:\"%s\"",
+                                 configoptions[k].keyword);
+
+           /* check for argument separated by '=' */
+            if ((ptr=strchr(ptr,'=')) == NULL) {;
+              ERROR("argument missing to config parameter %s",
+                    configoptions[k].keyword);
+              break;
+            }
+           do {ptr++;} while (*ptr == ' '); /* skip spaces after '=' */
+            
+            DEBUGC(DBCLASS_CONFIG,"got argument:\"%s\"",ptr);
+
+           num=0;
+           if (strlen(ptr) <= 0) {
+              WARN("empty argument in config file, line:\"%s\"",buff);
+              break;
+            }
+
+            switch (configoptions[k].type) {
+
+           //
+            // Integer4
+            //
+           case TYP_INT4:
+                num=sscanf(ptr,"%i",(int*)configoptions[k].dest);
+                 DEBUGC(DBCLASS_BABBLE,"INT4=%i",*(int*)configoptions[k].dest);
+             break;        
+
+           //
+           // String
+           //
+           case TYP_STRING:
+                /* the %as within sscanf seems to be not too portable.
+                  * it is supposed to allocate the memory
+                  * num=sscanf(ptr,"%as",(char**)configoptions[k].dest);
+                  */
+
+                /* figure out the amount of space we need */
+                num=strlen(ptr)+1; /* include terminating zero!*/
+                 tmpptr=(char*)malloc(num);
+                 memcpy(configoptions[k].dest, &tmpptr, sizeof(tmpptr));
+                num=sscanf(ptr,"%s",tmpptr);
+                 DEBUGC(DBCLASS_BABBLE,"STRING=%s",
+                         *(char**)configoptions[k].dest);
+             break;        
+
+           //
+           // String array
+           //
+           case TYP_STRINGA:
+            {
+                /* figure out the amount of space we need */
+                 char **dst;
+                 int used=((stringa_t*)(configoptions[k].dest))->used;
+                // do I hace space left?
+                 if (used<=CFG_STRARR_SIZE){
+                   num=strlen(ptr)+1; /* include terminating zero!*/
+                    tmpptr=(char*)malloc(num);
+                   dst=&((stringa_t*)(configoptions[k].dest))->
+                         string[used];
+                    memcpy(dst, &tmpptr, sizeof(tmpptr));
+                   num=sscanf(ptr,"%s",tmpptr);
+                   DEBUGC(DBCLASS_BABBLE,"STRINGA[%i]=%s", used, (char*) (
+                          ((stringa_t*)(configoptions[k].dest))->string[used]) );
+                   ((stringa_t*)(configoptions[k].dest))->used++;
+                 } else {
+                   ERROR("no more space left in config string array %s",
+                          configoptions[k].keyword);
+                 }
+             break;
+            }
+
+           default:
+             break;
+           }
+           if (num == 0) {
+              ERROR("illegal format in config file, line:\"%s\"",buff);
+           }
+
+            break;
+        }
+      } // for configoptions
+
+      /*
+       * complain if we hit a unknown keyword
+       */
+       if (configoptions[k].keyword == NULL) {
+         ERROR("unknown keyword in config file, line:\"%s\"",buff);
+       }
+   } // while
+   return STS_SUCCESS;
+}
+
+
+int make_default_config(void){
+   memset (&configuration, 0, sizeof(configuration));
+   configuration.sip_listen_port=SIP_PORT;
+   configuration.default_expires=DEFAULT_EXPIRES;
+
+   return STS_SUCCESS;
+}