- Second fixing-things pass: it even links now.
[oweals/tinc.git] / src / conf.c
1 /*
2     conf.c -- configuration code
3     Copyright (C) 1998 Emphyrio,
4     Copyright (C) 1998,1999,2000 Ivo Timmermans <itimmermans@bigfoot.com>
5                             2000 Guus Sliepen <guus@sliepen.warande.net>
6                             2000 Cris van Pelt <tribbel@arise.dhs.org>
7
8     This program is free software; you can redistribute it and/or modify
9     it under the terms of the GNU General Public License as published by
10     the Free Software Foundation; either version 2 of the License, or
11     (at your option) any later version.
12
13     This program is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU General Public License for more details.
17
18     You should have received a copy of the GNU General Public License
19     along with this program; if not, write to the Free Software
20     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
22     $Id: conf.c,v 1.9.4.13 2000/10/14 17:04:12 guus Exp $
23 */
24
25
26 #include <ctype.h>
27 #include <errno.h>
28 #include <netdb.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <syslog.h>
33
34 #include <xalloc.h>
35
36 #include "conf.h"
37 #include "netutl.h" /* for strtoip */
38 #include <utils.h> /* for cp */
39
40 #include "config.h"
41 #include "connlist.h"
42 #include "system.h"
43
44 config_t *config;
45 int debug_lvl = 0;
46 int timeout = 0; /* seconds before timeout */
47 char *confbase = NULL;           /* directory in which all config files are */
48
49 /* Will be set if HUP signal is received. It will be processed when it is safe. */
50 int sighup = 0;
51
52 /*
53   These are all the possible configurable values
54 */
55 static internal_config_t hazahaza[] = {
56 /* Main configuration file keywords */
57   { "Name",         tincname,       TYPE_NAME },
58   { "ConnectTo",    connectto,      TYPE_NAME },
59   { "PingTimeout",  pingtimeout,    TYPE_INT },
60   { "TapDevice",    tapdevice,      TYPE_NAME },
61   { "PrivateKey",   privatekey,     TYPE_NAME },
62   { "KeyExpire",    keyexpire,      TYPE_INT },
63   { "Hostnames",    resolve_dns,    TYPE_BOOL },
64   { "Interface",    interface,      TYPE_NAME },
65   { "InterfaceIP",  interfaceip,    TYPE_IP },
66 /* Host configuration file keywords */
67   { "Address",      address,        TYPE_NAME },
68   { "Port",         port,           TYPE_INT },
69   { "PublicKey",    publickey,      TYPE_NAME },
70   { "Subnet",       subnet,         TYPE_NAME },
71   { "RestrictHosts", restricthosts, TYPE_BOOL },
72   { "RestrictSubnets", restrictsubnets, TYPE_BOOL },
73   { "RestrictAddress", restrictaddress, TYPE_BOOL },
74   { "RestrictPort", restrictport,   TYPE_BOOL },
75   { "IndirectData", indirectdata,   TYPE_BOOL },
76   { "TCPonly",      tcponly,        TYPE_BOOL },
77   { NULL, 0, 0 }
78 };
79
80 /*
81   Add given value to the list of configs cfg
82 */
83 config_t *
84 add_config_val(config_t **cfg, int argtype, char *val)
85 {
86   config_t *p, *r;
87   char *q;
88 cp
89   p = (config_t*)xmalloc(sizeof(*p));
90   p->data.val = 0;
91   
92   switch(argtype)
93     {
94     case TYPE_INT:
95       p->data.val = strtol(val, &q, 0);
96       if(q && *q)
97         p->data.val = 0;
98       break;
99     case TYPE_NAME:
100       p->data.ptr = xmalloc(strlen(val) + 1);
101       strcpy(p->data.ptr, val);
102       break;
103     case TYPE_IP:
104       p->data.ip = strtoip(val);
105       break;
106     case TYPE_BOOL:
107       if(!strcasecmp("yes", val))
108         p->data.val = stupid_true;
109       else if(!strcasecmp("no", val))
110         p->data.val = stupid_false;
111       else
112         p->data.val = 0;
113     }
114
115   p->argtype = argtype;
116
117   if(p->data.val)
118     {
119       if(*cfg)
120         {
121           r = *cfg;
122           while(r->next)
123             r = r->next;
124           r->next = p;
125         }
126       else
127         *cfg = p;
128       p->next = NULL;
129       return p;
130     }
131
132   free(p);
133 cp
134   return NULL;
135 }
136
137 /*
138   Parse a configuration file and put the results in the configuration tree
139   starting at *base.
140 */
141 int read_config_file(config_t **base, const char *fname)
142 {
143   int err = -1;
144   FILE *fp;
145   char line[MAXBUFSIZE];        /* There really should not be any line longer than this... */
146   char *p, *q;
147   int i, lineno = 0;
148   config_t *cfg;
149 cp
150   if((fp = fopen (fname, "r")) == NULL)
151     {
152       return -1;
153     }
154
155   for(;;)
156     {
157       if(fgets(line, MAXBUFSIZE, fp) == NULL)
158         {
159           err = 0;
160           break;
161         }
162         
163       lineno++;
164
165       if(!index(line, '\n'))
166         {
167           syslog(LOG_ERR, _("Line %d too long while reading config file %s"), lineno, fname);
168           break;
169         }        
170
171       if((p = strtok(line, "\t\n\r =")) == NULL)
172         continue; /* no tokens on this line */
173
174       if(p[0] == '#')
175         continue; /* comment: ignore */
176
177       for(i = 0; hazahaza[i].name != NULL; i++)
178         if(!strcasecmp(hazahaza[i].name, p))
179           break;
180
181       if(!hazahaza[i].name)
182         {
183           syslog(LOG_ERR, _("Invalid variable name on line %d while reading config file %s"),
184                   lineno, fname);
185           break;
186         }
187
188       if(((q = strtok(NULL, "\t\n\r =")) == NULL) || q[0] == '#')
189         {
190           fprintf(stderr, _("No value for variable on line %d while reading config file %s"),
191                   lineno, fname);
192           break;
193         }
194
195       cfg = add_config_val(base, hazahaza[i].argtype, q);
196       if(cfg == NULL)
197         {
198           fprintf(stderr, _("Invalid value for variable on line %d while reading config file %s"),
199                   lineno, fname);
200           break;
201         }
202
203       cfg->which = hazahaza[i].which;
204       if(!config)
205         config = cfg;
206     }
207
208   fclose (fp);
209 cp
210   return err;
211 }
212
213 int read_server_config()
214 {
215   char *fname;
216   int x;
217 cp
218   asprintf(fname, "%s/tinc.conf", confbase);
219   x = read_config_file(&config, fname);
220   free(fname);
221 cp
222   return x;  
223 }
224
225 /*
226   Look up the value of the config option type
227 */
228 const config_t *get_config_val(config_t *p, which_t type)
229 {
230 cp
231   for(p = config; p != NULL; p = p->next)
232     if(p->which == type)
233       return p;
234 cp
235   /* Not found */
236   return NULL;
237 }
238
239 /*
240   Support for multiple config lines.
241   Index is used to get a specific value, 0 being the first, 1 the second etc.
242 */
243 const config_t *get_next_config_val(config_t *p, which_t type, int index)
244 {
245 cp  
246   for(p = config; p != NULL; p = p->next)
247     if(p->which == type)
248       if(--index < 0)
249         return p;
250 cp  
251   /* Not found */
252   return NULL;
253 }
254
255 /*
256   Remove the complete configuration tree.
257 */
258 void clear_config(config_t **base)
259 {
260   config_t *p, *next;
261 cp
262   for(p = *base; p != NULL; p = next)
263     {
264       next = p->next;
265       if(p->data.ptr && (p->argtype == TYPE_NAME))
266         {
267           free(p->data.ptr);
268         }
269       free(p);
270     }
271   *base = NULL;
272 cp
273 }