Cleanups.
[tinc] / src / conf.c
1 /*
2     conf.c -- configuration code
3     Copyright (C) 1998 Emphyrio,
4     Copyright (C) 1998,1999,2000 Ivo Timmermans <zarq@iname.com>
5
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "config.h"
22
23 #include <ctype.h>
24 #include <errno.h>
25 #include <netdb.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include <xalloc.h>
31
32 #include "conf.h"
33 #include "netutl.h" /* for strtoip */
34
35 config_t *config;
36 int debug_lvl = 0;
37 int timeout = 0; /* seconds before timeout */
38
39 typedef struct internal_config_t {
40   char *name;
41   enum which_t which;
42   int argtype;
43 } internal_config_t;
44
45 /*
46   These are all the possible configurable values
47 */
48 static internal_config_t hazahaza[] = {
49   { "AllowConnect", allowconnect,   TYPE_BOOL },   /* Is not used anywhere. Remove? */
50   { "ConnectTo",    upstreamip,     TYPE_IP },
51   { "ConnectPort",  upstreamport,   TYPE_INT },
52   { "ListenPort",   listenport,     TYPE_INT },
53   { "MyOwnVPNIP",   myvpnip,        TYPE_IP },
54   { "MyVirtualIP",  myvpnip,        TYPE_IP },   /* an alias */
55   { "Passphrases",  passphrasesdir, TYPE_NAME },
56   { "PingTimeout",  pingtimeout,    TYPE_INT },
57   { "TapDevice",    tapdevice,      TYPE_NAME },
58   { "KeyExpire",    keyexpire,      TYPE_INT },
59   { NULL, 0, 0 }
60 };
61
62 /*
63   Add given value to the list of configs cfg
64 */
65 config_t *
66 add_config_val(config_t **cfg, int argtype, char *val)
67 {
68   config_t *p;
69   char *q;
70
71   p = (config_t*)xmalloc(sizeof(*p));
72   p->data.val = 0;
73   
74   switch(argtype)
75     {
76     case TYPE_INT:
77       p->data.val = strtol(val, &q, 0);
78       if(q && *q)
79         p->data.val = 0;
80       break;
81     case TYPE_NAME:
82       p->data.ptr = xmalloc(strlen(val) + 1);
83       strcpy(p->data.ptr, val);
84       break;
85     case TYPE_IP:
86       p->data.ip = strtoip(val);
87       break;
88     case TYPE_BOOL:
89       if(!strcasecmp("yes", val))
90         p->data.val = stupid_true;
91       else if(!strcasecmp("no", val))
92         p->data.val = stupid_false;
93       else
94         p->data.val = 0;
95     }
96
97   if(p->data.val)
98     {
99       p->next = *cfg;
100       *cfg = p;
101       return p;
102     }
103
104   free(p);
105   return NULL;
106 }
107
108 /*
109   Get variable from a section in a configfile. returns -1 on failure.
110 */
111 int
112 readconfig(const char *fname, FILE *fp)
113 {
114   char line[81];
115   char *p, *q;
116   int i, lineno = 0;
117   config_t *cfg;
118
119   for(;;)
120     {
121       if(fgets(line, 80, fp) == NULL)
122         return 0;
123       lineno++;
124
125       if((p = strtok(line, "\t\n\r =")) == NULL)
126         continue; /* no tokens on this line */
127
128       if(p[0] == '#')
129         continue; /* comment: ignore */
130
131       for(i = 0; hazahaza[i].name != NULL; i++)
132         if(!strcasecmp(hazahaza[i].name, p))
133           break;
134
135       if(!hazahaza[i].name)
136         {
137           fprintf(stderr, "%s: %d: Invalid variable name `%s'.\n",
138                   fname, lineno, p);
139           return -1;
140         }
141
142       if(((q = strtok(NULL, "\t\n\r =")) == NULL) || q[0] == '#')
143         {
144           fprintf(stderr, "%s: %d: No value given for `%s'.\n",
145                   fname, lineno, hazahaza[i].name);
146           return -1;
147         }
148
149       cfg = add_config_val(&config, hazahaza[i].argtype, q);
150       if(cfg == NULL)
151         {
152           fprintf(stderr, "%s: %d: Invalid value `%s' for variable `%s'.\n",
153                   fname, lineno, q, hazahaza[i].name);
154           return -1;
155         }
156
157       cfg->which = hazahaza[i].which;
158       if(!config)
159         config = cfg;
160     }
161 }
162
163 /*
164   wrapper function for readconfig
165 */
166 int
167 read_config_file(const char *fname)
168 {
169   FILE *fp;
170
171   if((fp = fopen (fname, "r")) == NULL)
172     {
173       fprintf(stderr, "Could not open %s: %s\n", fname, sys_errlist[errno]);
174       return 1;
175     }
176
177   if(readconfig(fname, fp))
178     return -1;
179
180   fclose (fp);
181
182   return 0;
183 }
184
185 /*
186   Look up the value of the config option type
187 */
188 const config_t *
189 get_config_val(which_t type)
190 {
191   config_t *p;
192
193   for(p = config; p != NULL; p = p->next)
194     if(p->which == type)
195       return p;
196
197   /* Not found */
198   return NULL;
199 }