ca6640a794810622a94949b2eb3b453aed2f924f
[tinc] / 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.18 2000/10/29 00:02:17 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 #include <stdio.h>
34
35 #include <xalloc.h>
36
37 #include "conf.h"
38 #include "netutl.h" /* for strtoip */
39 #include <utils.h> /* for cp */
40
41 #include "config.h"
42 #include "connlist.h"
43 #include "system.h"
44
45 config_t *config = NULL;
46 int debug_lvl = 0;
47 int timeout = 0; /* seconds before timeout */
48 char *confbase = NULL;           /* directory in which all config files are */
49 char *netname = NULL;            /* name of the vpn network */
50
51 /* Will be set if HUP signal is received. It will be processed when it is safe. */
52 int sighup = 0;
53
54 /*
55   These are all the possible configurable values
56 */
57 static internal_config_t hazahaza[] = {
58 /* Main configuration file keywords */
59   { "Name",         tincname,       TYPE_NAME },
60   { "ConnectTo",    connectto,      TYPE_NAME },
61   { "PingTimeout",  pingtimeout,    TYPE_INT },
62   { "TapDevice",    tapdevice,      TYPE_NAME },
63   { "TapSubnet",    tapsubnet,      TYPE_IP },
64   { "PrivateKey",   privatekey,     TYPE_NAME },
65   { "KeyExpire",    keyexpire,      TYPE_INT },
66   { "Hostnames",    resolve_dns,    TYPE_BOOL },
67   { "Interface",    interface,      TYPE_NAME },
68   { "InterfaceIP",  interfaceip,    TYPE_IP },
69 /* Host configuration file keywords */
70   { "Address",      address,        TYPE_NAME },
71   { "Port",         port,           TYPE_INT },
72   { "PublicKey",    publickey,      TYPE_NAME },
73   { "Subnet",       subnet,         TYPE_IP },          /* Use IPv4 subnets only for now */
74   { "RestrictHosts", restricthosts, TYPE_BOOL },
75   { "RestrictSubnets", restrictsubnets, TYPE_BOOL },
76   { "RestrictAddress", restrictaddress, TYPE_BOOL },
77   { "RestrictPort", restrictport,   TYPE_BOOL },
78   { "IndirectData", indirectdata,   TYPE_BOOL },
79   { "TCPonly",      tcponly,        TYPE_BOOL },
80   { NULL, 0, 0 }
81 };
82
83 /*
84   Add given value to the list of configs cfg
85 */
86 config_t *
87 add_config_val(config_t **cfg, int argtype, char *val)
88 {
89   config_t *p;
90   char *q;
91 cp
92   p = (config_t*)xmalloc(sizeof(*p));
93   p->data.val = 0;
94
95   switch(argtype)
96     {
97     case TYPE_INT:
98       p->data.val = strtol(val, &q, 0);
99       if(q && *q)
100         p->data.val = 0;
101       break;
102     case TYPE_NAME:
103       p->data.ptr = xmalloc(strlen(val) + 1);
104       strcpy(p->data.ptr, val);
105       break;
106     case TYPE_IP:
107       p->data.ip = strtoip(val);
108       break;
109     case TYPE_BOOL:
110       if(!strcasecmp("yes", val))
111         p->data.val = stupid_true;
112       else if(!strcasecmp("no", val))
113         p->data.val = stupid_false;
114       else
115         p->data.val = 0;
116     }
117
118   p->argtype = argtype;
119
120   if(p->data.val)
121     {
122       p->next = *cfg;
123       *cfg = p;
124 cp
125       return p;
126     }
127   else
128     {
129       free(p);
130 cp
131       return NULL;
132     }
133 }
134
135 /*
136   Parse a configuration file and put the results in the configuration tree
137   starting at *base.
138 */
139 int read_config_file(config_t **base, const char *fname)
140 {
141   int err = -1;
142   FILE *fp;
143   char line[MAXBUFSIZE];        /* There really should not be any line longer than this... */
144   char *p, *q;
145   int i, lineno = 0;
146   config_t *cfg;
147 cp
148   if((fp = fopen (fname, "r")) == NULL)
149     {
150       return -1;
151     }
152
153   for(;;)
154     {
155       if(fgets(line, MAXBUFSIZE, fp) == NULL)
156         {
157           err = 0;
158           break;
159         }
160         
161       lineno++;
162
163       if(!index(line, '\n'))
164         {
165           syslog(LOG_ERR, _("Line %d too long while reading config file %s"), lineno, fname);
166           break;
167         }        
168
169       if((p = strtok(line, "\t\n\r =")) == NULL)
170         continue; /* no tokens on this line */
171
172       if(p[0] == '#')
173         continue; /* comment: ignore */
174
175       for(i = 0; hazahaza[i].name != NULL; i++)
176         if(!strcasecmp(hazahaza[i].name, p))
177           break;
178
179       if(!hazahaza[i].name)
180         {
181           syslog(LOG_ERR, _("Invalid variable name on line %d while reading config file %s"),
182                   lineno, fname);
183           break;
184         }
185
186       if(((q = strtok(NULL, "\t\n\r =")) == NULL) || q[0] == '#')
187         {
188           fprintf(stderr, _("No value for variable on line %d while reading config file %s"),
189                   lineno, fname);
190           break;
191         }
192
193       cfg = add_config_val(base, hazahaza[i].argtype, q);
194       if(cfg == NULL)
195         {
196           fprintf(stderr, _("Invalid value for variable on line %d while reading config file %s"),
197                   lineno, fname);
198           break;
199         }
200
201       cfg->which = hazahaza[i].which;
202       if(!config)
203         config = cfg;
204     }
205
206   fclose (fp);
207 cp
208   return err;
209 }
210
211 int read_server_config()
212 {
213   char *fname;
214   int x;
215 cp
216   asprintf(&fname, "%s/tinc.conf", confbase);
217   x = read_config_file(&config, fname);
218   if(x != 0)
219     {
220       fprintf(stderr, _("Failed to read `%s': %m\n"),
221               fname);
222     }
223   free(fname);
224 cp
225   return x;  
226 }
227
228 /*
229   Look up the value of the config option type
230 */
231 const config_t *get_config_val(config_t *p, which_t type)
232 {
233 cp
234   for(; p != NULL; p = p->next)
235     if(p->which == type)
236       break;
237 cp
238   return p;
239 }
240
241 /*
242   Remove the complete configuration tree.
243 */
244 void clear_config(config_t **base)
245 {
246   config_t *p, *next;
247 cp
248   for(p = *base; p != NULL; p = next)
249     {
250       next = p->next;
251       if(p->data.ptr && (p->argtype == TYPE_NAME))
252         {
253           free(p->data.ptr);
254         }
255       free(p);
256     }
257   *base = NULL;
258 cp
259 }