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