2000-03-26 00:33:07 +00:00
|
|
|
/*
|
|
|
|
conf.c -- configuration code
|
|
|
|
Copyright (C) 1998 Emphyrio,
|
2000-05-30 11:18:12 +00:00
|
|
|
Copyright (C) 1998,1999,2000 Ivo Timmermans <itimmermans@bigfoot.com>
|
|
|
|
2000 Guus Sliepen <guus@sliepen.warande.net>
|
|
|
|
2000 Cris van Pelt <tribbel@arise.dhs.org>
|
2000-03-26 00:33:07 +00:00
|
|
|
|
|
|
|
This program 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.
|
|
|
|
|
|
|
|
This program 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 this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
2000-05-30 11:18:12 +00:00
|
|
|
|
2000-11-04 22:57:33 +00:00
|
|
|
$Id: conf.c,v 1.9.4.21 2000/11/04 22:57:30 guus Exp $
|
2000-03-26 00:33:07 +00:00
|
|
|
*/
|
|
|
|
|
2000-11-03 22:35:12 +00:00
|
|
|
#include "config.h"
|
2000-05-15 18:28:45 +00:00
|
|
|
|
2000-03-26 00:33:07 +00:00
|
|
|
#include <ctype.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <netdb.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2000-10-11 22:01:02 +00:00
|
|
|
#include <syslog.h>
|
2000-03-26 00:33:07 +00:00
|
|
|
|
|
|
|
#include <xalloc.h>
|
|
|
|
|
|
|
|
#include "conf.h"
|
|
|
|
#include "netutl.h" /* for strtoip */
|
2000-06-29 19:47:04 +00:00
|
|
|
#include <utils.h> /* for cp */
|
2000-03-26 00:33:07 +00:00
|
|
|
|
2000-10-11 22:01:02 +00:00
|
|
|
#include "config.h"
|
2000-10-14 17:04:16 +00:00
|
|
|
#include "connlist.h"
|
2000-05-29 21:01:26 +00:00
|
|
|
#include "system.h"
|
|
|
|
|
2000-10-15 00:59:37 +00:00
|
|
|
config_t *config = NULL;
|
2000-03-26 00:33:07 +00:00
|
|
|
int debug_lvl = 0;
|
|
|
|
int timeout = 0; /* seconds before timeout */
|
2000-10-14 17:04:16 +00:00
|
|
|
char *confbase = NULL; /* directory in which all config files are */
|
2000-10-15 00:59:37 +00:00
|
|
|
char *netname = NULL; /* name of the vpn network */
|
2000-06-29 19:47:04 +00:00
|
|
|
|
|
|
|
/* Will be set if HUP signal is received. It will be processed when it is safe. */
|
|
|
|
int sighup = 0;
|
2000-03-26 00:33:07 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
These are all the possible configurable values
|
|
|
|
*/
|
|
|
|
static internal_config_t hazahaza[] = {
|
2000-10-11 13:42:52 +00:00
|
|
|
/* Main configuration file keywords */
|
2000-11-04 22:57:33 +00:00
|
|
|
{ "Name", config_name, TYPE_NAME },
|
|
|
|
{ "ConnectTo", config_connectto, TYPE_NAME },
|
|
|
|
{ "PingTimeout", config_pingtimeout, TYPE_INT },
|
|
|
|
{ "TapDevice", config_tapdevice, TYPE_NAME },
|
|
|
|
{ "PrivateKey", config_privatekey, TYPE_NAME },
|
|
|
|
{ "KeyExpire", config_keyexpire, TYPE_INT },
|
|
|
|
{ "Hostnames", config_hostnames, TYPE_BOOL },
|
|
|
|
{ "Interface", config_interface, TYPE_NAME },
|
|
|
|
{ "InterfaceIP", config_interfaceip, TYPE_IP },
|
2000-10-11 13:42:52 +00:00
|
|
|
/* Host configuration file keywords */
|
2000-11-04 22:57:33 +00:00
|
|
|
{ "Address", config_address, TYPE_NAME },
|
|
|
|
{ "Port", config_port, TYPE_INT },
|
|
|
|
{ "PublicKey", config_publickey, TYPE_NAME },
|
|
|
|
{ "Subnet", config_subnet, TYPE_IP }, /* Use IPv4 subnets only for now */
|
|
|
|
{ "RestrictHosts", config_restricthosts, TYPE_BOOL },
|
|
|
|
{ "RestrictSubnets", config_restrictsubnets, TYPE_BOOL },
|
|
|
|
{ "RestrictAddress", config_restrictaddress, TYPE_BOOL },
|
|
|
|
{ "RestrictPort", config_restrictport, TYPE_BOOL },
|
|
|
|
{ "IndirectData", config_indirectdata, TYPE_BOOL },
|
|
|
|
{ "TCPonly", config_tcponly, TYPE_BOOL },
|
2000-03-26 00:33:07 +00:00
|
|
|
{ NULL, 0, 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
Add given value to the list of configs cfg
|
|
|
|
*/
|
|
|
|
config_t *
|
|
|
|
add_config_val(config_t **cfg, int argtype, char *val)
|
|
|
|
{
|
2000-10-29 00:02:20 +00:00
|
|
|
config_t *p;
|
2000-03-26 00:33:07 +00:00
|
|
|
char *q;
|
2000-06-29 19:47:04 +00:00
|
|
|
cp
|
2000-04-26 17:42:55 +00:00
|
|
|
p = (config_t*)xmalloc(sizeof(*p));
|
2000-03-26 00:33:07 +00:00
|
|
|
p->data.val = 0;
|
2000-10-16 16:33:30 +00:00
|
|
|
|
2000-03-26 00:33:07 +00:00
|
|
|
switch(argtype)
|
|
|
|
{
|
|
|
|
case TYPE_INT:
|
|
|
|
p->data.val = strtol(val, &q, 0);
|
|
|
|
if(q && *q)
|
|
|
|
p->data.val = 0;
|
|
|
|
break;
|
|
|
|
case TYPE_NAME:
|
|
|
|
p->data.ptr = xmalloc(strlen(val) + 1);
|
|
|
|
strcpy(p->data.ptr, val);
|
|
|
|
break;
|
|
|
|
case TYPE_IP:
|
|
|
|
p->data.ip = strtoip(val);
|
|
|
|
break;
|
|
|
|
case TYPE_BOOL:
|
|
|
|
if(!strcasecmp("yes", val))
|
|
|
|
p->data.val = stupid_true;
|
|
|
|
else if(!strcasecmp("no", val))
|
|
|
|
p->data.val = stupid_false;
|
|
|
|
else
|
|
|
|
p->data.val = 0;
|
|
|
|
}
|
|
|
|
|
2000-06-30 11:45:16 +00:00
|
|
|
p->argtype = argtype;
|
|
|
|
|
2000-03-26 00:33:07 +00:00
|
|
|
if(p->data.val)
|
|
|
|
{
|
2000-10-15 00:59:37 +00:00
|
|
|
p->next = *cfg;
|
|
|
|
*cfg = p;
|
|
|
|
cp
|
2000-03-26 00:33:07 +00:00
|
|
|
return p;
|
|
|
|
}
|
2000-10-15 00:59:37 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
free(p);
|
2000-06-29 19:47:04 +00:00
|
|
|
cp
|
2000-10-15 00:59:37 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2000-03-26 00:33:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2000-10-11 13:42:52 +00:00
|
|
|
Parse a configuration file and put the results in the configuration tree
|
|
|
|
starting at *base.
|
2000-03-26 00:33:07 +00:00
|
|
|
*/
|
2000-10-11 13:42:52 +00:00
|
|
|
int read_config_file(config_t **base, const char *fname)
|
2000-03-26 00:33:07 +00:00
|
|
|
{
|
2000-10-11 22:01:02 +00:00
|
|
|
int err = -1;
|
2000-10-11 13:42:52 +00:00
|
|
|
FILE *fp;
|
|
|
|
char line[MAXBUFSIZE]; /* There really should not be any line longer than this... */
|
2000-03-26 00:33:07 +00:00
|
|
|
char *p, *q;
|
2000-10-11 22:01:02 +00:00
|
|
|
int i, lineno = 0;
|
2000-03-26 00:33:07 +00:00
|
|
|
config_t *cfg;
|
2000-06-29 19:47:04 +00:00
|
|
|
cp
|
2000-10-11 13:42:52 +00:00
|
|
|
if((fp = fopen (fname, "r")) == NULL)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2000-03-26 00:33:07 +00:00
|
|
|
for(;;)
|
|
|
|
{
|
2000-10-11 13:42:52 +00:00
|
|
|
if(fgets(line, MAXBUFSIZE, fp) == NULL)
|
|
|
|
{
|
|
|
|
err = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
lineno++;
|
2000-05-15 18:28:45 +00:00
|
|
|
|
2000-10-11 13:42:52 +00:00
|
|
|
if(!index(line, '\n'))
|
2000-05-15 18:28:45 +00:00
|
|
|
{
|
2000-10-11 13:42:52 +00:00
|
|
|
syslog(LOG_ERR, _("Line %d too long while reading config file %s"), lineno, fname);
|
|
|
|
break;
|
2000-05-15 18:28:45 +00:00
|
|
|
}
|
2000-03-26 00:33:07 +00:00
|
|
|
|
|
|
|
if((p = strtok(line, "\t\n\r =")) == NULL)
|
|
|
|
continue; /* no tokens on this line */
|
|
|
|
|
|
|
|
if(p[0] == '#')
|
|
|
|
continue; /* comment: ignore */
|
|
|
|
|
|
|
|
for(i = 0; hazahaza[i].name != NULL; i++)
|
|
|
|
if(!strcasecmp(hazahaza[i].name, p))
|
|
|
|
break;
|
|
|
|
|
|
|
|
if(!hazahaza[i].name)
|
|
|
|
{
|
2000-10-11 13:42:52 +00:00
|
|
|
syslog(LOG_ERR, _("Invalid variable name on line %d while reading config file %s"),
|
|
|
|
lineno, fname);
|
|
|
|
break;
|
2000-03-26 00:33:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(((q = strtok(NULL, "\t\n\r =")) == NULL) || q[0] == '#')
|
|
|
|
{
|
2000-10-11 13:42:52 +00:00
|
|
|
fprintf(stderr, _("No value for variable on line %d while reading config file %s"),
|
|
|
|
lineno, fname);
|
|
|
|
break;
|
2000-03-26 00:33:07 +00:00
|
|
|
}
|
|
|
|
|
2000-10-11 13:42:52 +00:00
|
|
|
cfg = add_config_val(base, hazahaza[i].argtype, q);
|
2000-03-26 00:33:07 +00:00
|
|
|
if(cfg == NULL)
|
|
|
|
{
|
2000-10-11 13:42:52 +00:00
|
|
|
fprintf(stderr, _("Invalid value for variable on line %d while reading config file %s"),
|
|
|
|
lineno, fname);
|
|
|
|
break;
|
2000-03-26 00:33:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
cfg->which = hazahaza[i].which;
|
|
|
|
if(!config)
|
|
|
|
config = cfg;
|
|
|
|
}
|
|
|
|
|
|
|
|
fclose (fp);
|
2000-06-29 19:47:04 +00:00
|
|
|
cp
|
2000-06-30 11:45:16 +00:00
|
|
|
return err;
|
2000-03-26 00:33:07 +00:00
|
|
|
}
|
|
|
|
|
2000-10-14 17:04:16 +00:00
|
|
|
int read_server_config()
|
|
|
|
{
|
|
|
|
char *fname;
|
|
|
|
int x;
|
|
|
|
cp
|
2000-10-15 00:59:37 +00:00
|
|
|
asprintf(&fname, "%s/tinc.conf", confbase);
|
2000-10-14 17:04:16 +00:00
|
|
|
x = read_config_file(&config, fname);
|
2000-10-22 13:47:41 +00:00
|
|
|
if(x != 0)
|
|
|
|
{
|
|
|
|
fprintf(stderr, _("Failed to read `%s': %m\n"),
|
|
|
|
fname);
|
|
|
|
}
|
2000-10-14 17:04:16 +00:00
|
|
|
free(fname);
|
|
|
|
cp
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
2000-03-26 00:33:07 +00:00
|
|
|
/*
|
|
|
|
Look up the value of the config option type
|
|
|
|
*/
|
2000-10-11 13:42:52 +00:00
|
|
|
const config_t *get_config_val(config_t *p, which_t type)
|
2000-03-26 00:33:07 +00:00
|
|
|
{
|
2000-06-29 19:47:04 +00:00
|
|
|
cp
|
2000-10-16 16:33:30 +00:00
|
|
|
for(; p != NULL; p = p->next)
|
2000-03-26 00:33:07 +00:00
|
|
|
if(p->which == type)
|
2000-10-15 00:59:37 +00:00
|
|
|
break;
|
2000-06-29 19:47:04 +00:00
|
|
|
cp
|
2000-10-15 00:59:37 +00:00
|
|
|
return p;
|
2000-03-26 00:33:07 +00:00
|
|
|
}
|
2000-06-27 15:08:58 +00:00
|
|
|
|
2000-06-29 19:47:04 +00:00
|
|
|
/*
|
|
|
|
Remove the complete configuration tree.
|
|
|
|
*/
|
2000-10-11 13:42:52 +00:00
|
|
|
void clear_config(config_t **base)
|
2000-06-29 19:47:04 +00:00
|
|
|
{
|
|
|
|
config_t *p, *next;
|
|
|
|
cp
|
2000-10-11 13:42:52 +00:00
|
|
|
for(p = *base; p != NULL; p = next)
|
2000-06-29 19:47:04 +00:00
|
|
|
{
|
|
|
|
next = p->next;
|
2000-06-30 11:45:16 +00:00
|
|
|
if(p->data.ptr && (p->argtype == TYPE_NAME))
|
|
|
|
{
|
|
|
|
free(p->data.ptr);
|
|
|
|
}
|
2000-06-29 19:47:04 +00:00
|
|
|
free(p);
|
|
|
|
}
|
2000-10-11 13:42:52 +00:00
|
|
|
*base = NULL;
|
2000-06-29 19:47:04 +00:00
|
|
|
cp
|
|
|
|
}
|