ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/conf.C
(Generate patch)

Comparing gvpe/src/conf.C (file contents):
Revision 1.11 by pcg, Wed Apr 2 21:43:44 2003 UTC vs.
Revision 1.55 by root, Sun Mar 6 19:40:28 2011 UTC

1/* 1/*
2 conf.c -- configuration code 2 conf.C -- configuration code
3 Copyright (C) 1998 Robert van der Meulen 3 Copyright (C) 2003-2008,2011 Marc Lehmann <gvpe@schmorp.de>
4 1998-2002 Ivo Timmermans <ivo@o2w.nl>
5 2000-2002 Guus Sliepen <guus@sliepen.eu.org>
6 2000 Cris van Pelt <tribbel@arise.dhs.org>
7 2003 Marc Lehmann <pcg@goof.com>
8 4
5 This file is part of GVPE.
6
9 This program is free software; you can redistribute it and/or modify 7 GVPE is free software; you can redistribute it and/or modify it
10 it under the terms of the GNU General Public License as published by 8 under the terms of the GNU General Public License as published by the
11 the Free Software Foundation; either version 2 of the License, or 9 Free Software Foundation; either version 3 of the License, or (at your
12 (at your option) any later version. 10 option) any later version.
13 11
14 This program is distributed in the hope that it will be useful, 12 This program is distributed in the hope that it will be useful, but
15 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17 GNU General Public License for more details. 15 Public License for more details.
18 16
19 You should have received a copy of the GNU General Public License 17 You should have received a copy of the GNU General Public License along
20 along with this program; if not, write to the Free Software 18 with this program; if not, see <http://www.gnu.org/licenses/>.
21 Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19
20 Additional permission under GNU GPL version 3 section 7
21
22 If you modify this Program, or any covered work, by linking or
23 combining it with the OpenSSL project's OpenSSL library (or a modified
24 version of that library), containing parts covered by the terms of the
25 OpenSSL or SSLeay licenses, the licensors of this Program grant you
26 additional permission to convey the resulting work. Corresponding
27 Source for a non-source form of such a combination shall include the
28 source code for the parts of OpenSSL used as well as that of the
29 covered work.
22*/ 30*/
23 31
24#include "config.h" 32#include "config.h"
25 33
26#include <cstdio> 34#include <cstdio>
31#include <netdb.h> 39#include <netdb.h>
32#include <sys/stat.h> 40#include <sys/stat.h>
33#include <sys/types.h> 41#include <sys/types.h>
34#include <unistd.h> 42#include <unistd.h>
35 43
36#include <netinet/in.h> 44#include "netcompat.h"
37 45
38#include <openssl/err.h> 46#include <openssl/err.h>
39#include <openssl/pem.h> 47#include <openssl/pem.h>
40#include <openssl/rsa.h> 48#include <openssl/rsa.h>
41#include <openssl/rand.h> 49#include <openssl/rand.h>
42 50#include <openssl/bn.h>
43#include "gettext.h"
44 51
45#include "conf.h" 52#include "conf.h"
46#include "slog.h" 53#include "slog.h"
47#include "util.h" 54#include "util.h"
48 55
49char *confbase; 56char *confbase;
50char *thisnode; 57char *thisnode;
51char *identname; 58char *identname;
52char *pidfilename;
53 59
54struct configuration conf; 60struct configuration conf;
55 61
62u8
56u8 best_protocol (u8 protset) 63best_protocol (u8 protset)
57{ 64{
58 if (protset & PROT_IPv4 ) return PROT_IPv4; 65 if (protset & PROT_IPv4 ) return PROT_IPv4;
66 if (protset & PROT_ICMPv4) return PROT_ICMPv4;
59 if (protset & PROT_UDPv4) return PROT_UDPv4; 67 if (protset & PROT_UDPv4 ) return PROT_UDPv4;
60 if (protset & PROT_TCPv4) return PROT_TCPv4; 68 if (protset & PROT_TCPv4 ) return PROT_TCPv4;
69 if (protset & PROT_DNSv4 ) return PROT_DNSv4;
61 70
62 return 0; 71 return 0;
63} 72}
64 73
74const char *
65const char *strprotocol (u8 protocol) 75strprotocol (u8 protocol)
66{ 76{
67 if (protocol & PROT_IPv4 ) return "rawip"; 77 if (protocol & PROT_IPv4 ) return "rawip";
78 if (protocol & PROT_ICMPv4) return "icmp";
68 if (protocol & PROT_UDPv4) return "udp"; 79 if (protocol & PROT_UDPv4 ) return "udp";
69 if (protocol & PROT_TCPv4) return "tcp"; 80 if (protocol & PROT_TCPv4 ) return "tcp";
81 if (protocol & PROT_DNSv4 ) return "dns";
70 82
71 return "<unknown>"; 83 return "<unknown>";
72} 84}
73 85
74configuration::configuration () 86static bool
87match_list (const vector<const char *> &list, const char *str)
75{ 88{
76 init (); 89 for (vector<const char *>::const_iterator i = list.end (); i-- > list.begin (); )
77} 90 if ((*i)[0] == '*' && !(*i)[1])
91 return true;
92 else if (!strcmp (*i, str))
93 return true;
78 94
79configuration::~configuration () 95 return false;
80{
81 cleanup ();
82} 96}
83 97
98bool
99conf_node::may_direct (struct conf_node *other)
100{
101 if (match_list (allow_direct, other->nodename))
102 return true;
103
104 if (match_list (deny_direct, other->nodename))
105 return false;
106
107 return true;
108}
109
110conf_node::~conf_node ()
111{
112#if 0
113 // does not work, because string pointers etc. are shared
114 // is not called, however
115 if (rsa_key)
116 RSA_free (rsa_key);
117
118 free (nodename);
119 free (hostname);
120 free (if_up_data);
121#if ENABLE_DNS
122 free (domain);
123 free (dns_hostname);
124#endif
125#endif
126}
127
128void
84void configuration::init () 129configuration::init ()
85{ 130{
86 memset (this, 0, sizeof (*this)); 131 memset (this, 0, sizeof (*this));
87 132
133 mtu = DEFAULT_MTU;
134 nfmark = 0;
88 rekey = DEFAULT_REKEY; 135 rekey = DEFAULT_REKEY;
89 keepalive = DEFAULT_KEEPALIVE; 136 keepalive = DEFAULT_KEEPALIVE;
90 llevel = L_INFO; 137 llevel = L_INFO;
91 ip_proto = IPPROTO_GRE; 138 ip_proto = IPPROTO_GRE;
139#if ENABLE_ICMP
140 icmp_type = ICMP_ECHOREPLY;
141#endif
92 142
93 default_node.udp_port = DEFAULT_UDPPORT; 143 default_node.udp_port = DEFAULT_UDPPORT;
94 default_node.tcp_port = DEFAULT_UDPPORT; 144 default_node.tcp_port = DEFAULT_UDPPORT; // ehrm
95 default_node.connectmode = conf_node::C_ALWAYS; 145 default_node.connectmode = conf_node::C_ALWAYS;
96 default_node.compress = true; 146 default_node.compress = true;
97 default_node.protocols = PROT_UDPv4; 147 default_node.protocols = 0;
98} 148 default_node.max_retry = DEFAULT_MAX_RETRY;
149 default_node.max_ttl = DEFAULT_MAX_TTL;
150 default_node.max_queue = DEFAULT_MAX_QUEUE;
151 default_node.if_up_data = strdup ("");
99 152
153#if ENABLE_DNS
154 default_node.dns_port = 0; // default is 0 == client
155
156 dns_case_preserving = true;
157 dns_forw_host = strdup ("127.0.0.1");
158 dns_forw_port = 53;
159 dns_timeout_factor = DEFAULT_DNS_TIMEOUT_FACTOR;
160 dns_send_interval = DEFAULT_DNS_SEND_INTERVAL;
161 dns_overlap_factor = DEFAULT_DNS_OVERLAP_FACTOR;
162 dns_max_outstanding = DEFAULT_DNS_MAX_OUTSTANDING;
163#endif
164
165 conf.pidfilename = strdup (LOCALSTATEDIR "/run/gvpe.pid");
166}
167
168void
100void configuration::cleanup() 169configuration::cleanup ()
101{ 170{
102 if (rsa_key) 171 if (rsa_key)
103 RSA_free (rsa_key); 172 RSA_free (rsa_key);
104 173
105 free (ifname);
106
107 rsa_key = 0; 174 rsa_key = 0;
108 ifname = 0; 175
176 free (pidfilename); pidfilename = 0;
177 free (ifname); ifname = 0;
178#if ENABLE_HTTP_PROXY
179 free (proxy_host); proxy_host = 0;
180 free (proxy_auth); proxy_auth = 0;
181#endif
182#if ENABLE_DNS
183 free (dns_forw_host); dns_forw_host = 0;
184#endif
185 free (script_if_up); script_if_up = 0;
186 free (script_node_up); script_node_up = 0;
187 free (script_node_change); script_node_change = 0;
188 free (script_node_down); script_node_down = 0;
109} 189}
110 190
111void 191void
112configuration::clear_config () 192configuration::clear ()
113{ 193{
114 for (configuration::node_vector::iterator i = nodes.begin(); i != nodes.end(); ++i) 194 for (configuration::node_vector::iterator i = nodes.begin(); i != nodes.end(); ++i)
115 delete *i; 195 delete *i;
116 196
117 nodes.clear (); 197 nodes.clear ();
118 198
119 cleanup (); 199 cleanup ();
120 init (); 200 init ();
121} 201}
122 202
203//static bool
204//is_true (const char *name)
205//{
206 //re
207//}
208
123#define parse_bool(target,name,trueval,falseval) \ 209#define parse_bool(target,name,trueval,falseval) do { \
124 if (!strcmp (val, "yes")) target = trueval; \ 210 if (!strcmp (val, "yes")) target = trueval; \
125 else if (!strcmp (val, "no")) target = falseval; \ 211 else if (!strcmp (val, "no")) target = falseval; \
126 else if (!strcmp (val, "true")) target = trueval; \ 212 else if (!strcmp (val, "true")) target = trueval; \
127 else if (!strcmp (val, "false")) target = falseval; \ 213 else if (!strcmp (val, "false")) target = falseval; \
128 else if (!strcmp (val, "on")) target = trueval; \ 214 else if (!strcmp (val, "on")) target = trueval; \
129 else if (!strcmp (val, "off")) target = falseval; \ 215 else if (!strcmp (val, "off")) target = falseval; \
130 else \ 216 else \
131 slog (L_WARN, \ 217 return _("illegal boolean value, only 'yes|true|on' or 'no|false|off' allowed. (ignored)"); \
132 _("illegal value for '%s', only 'yes|true|on' or 'no|false|off' allowed, at '%s' line %d"), \ 218} while (0)
133 name, var, fname, lineno);
134 219
135void configuration::read_config (bool need_keys) 220const char *
221configuration_parser::parse_line (char *line)
136{ 222{
223 {
224 char *end = line + strlen (line);
225
226 while (*end < ' ' && end >= line)
227 end--;
228
229 *++end = 0;
230 }
231
232 char *tok = line;
233 const char *var = strtok (tok, "\t =");
234 tok = 0;
235
236 if (!var || !var[0])
237 return 0; /* no tokens on this line */
238
239 if (var[0] == '#')
240 return 0; /* comment: ignore */
241
242 char *val = strtok (NULL, "\t\n\r =");
243
244 if (!val || val[0] == '#')
245 return _("no value given for variable. (ignored)");
246
247 else if (!strcmp (var, "on"))
248 {
249 if (!::thisnode
250 || (val[0] == '!' && strcmp (val + 1, ::thisnode))
251 || !strcmp (val, ::thisnode))
252 return parse_line (strtok (NULL, "\n\r"));
253 }
254
255 else if (!strcmp (var, "include"))
256 {
257 char *fname = conf.config_filename (val);
258 parse_file (fname);
259 free (fname);
260 }
261
262 // truly global
263 else if (!strcmp (var, "loglevel"))
264 {
265 loglevel l = string_to_loglevel (val);
266
267 if (l == L_NONE)
268 return _("unknown loglevel. (skipping)");
269 }
270 else if (!strcmp (var, "ip-proto"))
271 conf.ip_proto = atoi (val);
272 else if (!strcmp (var, "icmp-type"))
273 {
274#if ENABLE_ICMP
275 conf.icmp_type = atoi (val);
276#endif
277 }
278
279 // per config
280 else if (!strcmp (var, "node"))
281 {
282 parse_argv ();
283
284 conf.default_node.id++;
285 node = new conf_node (conf.default_node);
286 conf.nodes.push_back (node);
287 node->nodename = strdup (val);
288
289 {
137 char *fname; 290 char *fname;
138 FILE *f; 291 FILE *f;
139 292
140 clear_config (); 293 asprintf (&fname, "%s/pubkey/%s", confbase, node->nodename);
141 294
142 asprintf (&fname, "%s/vped.conf", confbase);
143 f = fopen (fname, "r"); 295 f = fopen (fname, "r");
296 if (f)
297 {
298 node->rsa_key = RSA_new ();
144 299
145 if (f) 300 if (!PEM_read_RSAPublicKey(f, &node->rsa_key, NULL, NULL))
301 {
302 ERR_load_RSA_strings (); ERR_load_PEM_strings ();
303 slog (L_ERR, _("unable to open public rsa key file '%s': %s"), fname, ERR_error_string (ERR_get_error (), 0));
304 exit (EXIT_FAILURE);
305 }
306
307 require (RSA_blinding_on (node->rsa_key, 0));
308
309 fclose (f);
310 }
311 else
312 {
313 slog (need_keys ? L_ERR : L_NOTICE, _("unable to read public rsa key file '%s': %s"), fname, strerror (errno));
314
315 if (need_keys)
316 exit (EXIT_FAILURE);
317 }
318
319 free (fname);
320 }
321
322 if (::thisnode && !strcmp (node->nodename, ::thisnode))
323 conf.thisnode = node;
146 { 324 }
325 else if (!strcmp (var, "private-key"))
326 free (conf.prikeyfile), conf.prikeyfile = strdup (val);
327 else if (!strcmp (var, "ifpersist"))
328 parse_bool (conf.ifpersist, "ifpersist", true, false);
329 else if (!strcmp (var, "ifname"))
330 free (conf.ifname), conf.ifname = strdup (val);
331 else if (!strcmp (var, "rekey"))
332 conf.rekey = atoi (val);
333 else if (!strcmp (var, "keepalive"))
334 conf.keepalive = atoi (val);
335 else if (!strcmp (var, "mtu"))
336 conf.mtu = atoi (val);
337 else if (!strcmp (var, "nfmark"))
338 conf.nfmark = atoi (val);
339 else if (!strcmp (var, "if-up"))
340 free (conf.script_if_up), conf.script_if_up = strdup (val);
341 else if (!strcmp (var, "node-up"))
342 free (conf.script_node_up), conf.script_node_up = strdup (val);
343 else if (!strcmp (var, "node-change"))
344 free (conf.script_node_change), conf.script_node_change = strdup (val);
345 else if (!strcmp (var, "node-down"))
346 free (conf.script_node_down), conf.script_node_down = strdup (val);
347 else if (!strcmp (var, "pid-file"))
348 free (conf.pidfilename), conf.pidfilename = strdup (val);
349 else if (!strcmp (var, "dns-forw-host"))
350 {
351#if ENABLE_DNS
352 free (conf.dns_forw_host), conf.dns_forw_host = strdup (val);
353#endif
354 }
355 else if (!strcmp (var, "dns-forw-port"))
356 {
357#if ENABLE_DNS
358 conf.dns_forw_port = atoi (val);
359#endif
360 }
361 else if (!strcmp (var, "dns-timeout-factor"))
362 {
363#if ENABLE_DNS
364 conf.dns_timeout_factor = atof (val);
365#endif
366 }
367 else if (!strcmp (var, "dns-send-interval"))
368 {
369#if ENABLE_DNS
370 conf.dns_send_interval = atoi (val);
371#endif
372 }
373 else if (!strcmp (var, "dns-overlap-factor"))
374 {
375#if ENABLE_DNS
376 conf.dns_overlap_factor = atof (val);
377#endif
378 }
379 else if (!strcmp (var, "dns-max-outstanding"))
380 {
381#if ENABLE_DNS
382 conf.dns_max_outstanding = atoi (val);
383#endif
384 }
385 else if (!strcmp (var, "dns-case-preserving"))
386 {
387#if ENABLE_DNS
388 parse_bool (conf.dns_case_preserving, "dns-case-preserving", true, false);
389#endif
390 }
391 else if (!strcmp (var, "http-proxy-host"))
392 {
393#if ENABLE_HTTP_PROXY
394 free (conf.proxy_host), conf.proxy_host = strdup (val);
395#endif
396 }
397 else if (!strcmp (var, "http-proxy-port"))
398 {
399#if ENABLE_HTTP_PROXY
400 conf.proxy_port = atoi (val);
401#endif
402 }
403 else if (!strcmp (var, "http-proxy-auth"))
404 {
405#if ENABLE_HTTP_PROXY
406 conf.proxy_auth = (char *)base64_encode ((const u8 *)val, strlen (val));
407#endif
408 }
409
410 /* node-specific, non-defaultable */
411 else if (node != &conf.default_node && !strcmp (var, "hostname"))
412 free (node->hostname), node->hostname = strdup (val);
413
414 /* node-specific, defaultable */
415 else if (!strcmp (var, "udp-port"))
416 node->udp_port = atoi (val);
417 else if (!strcmp (var, "tcp-port"))
418 node->tcp_port = atoi (val);
419 else if (!strcmp (var, "dns-hostname"))
420 {
421#if ENABLE_DNS
422 free (node->dns_hostname), node->dns_hostname = strdup (val);
423#endif
424 }
425 else if (!strcmp (var, "dns-port"))
426 {
427#if ENABLE_DNS
428 node->dns_port = atoi (val);
429#endif
430 }
431 else if (!strcmp (var, "dns-domain"))
432 {
433#if ENABLE_DNS
434 free (node->domain), node->domain = strdup (val);
435#endif
436 }
437 else if (!strcmp (var, "if-up-data"))
438 free (node->if_up_data), node->if_up_data = strdup (val);
439 else if (!strcmp (var, "router-priority"))
440 node->routerprio = atoi (val);
441 else if (!strcmp (var, "max-retry"))
442 node->max_retry = atoi (val);
443 else if (!strcmp (var, "connect"))
444 {
445 if (!strcmp (val, "ondemand"))
446 node->connectmode = conf_node::C_ONDEMAND;
447 else if (!strcmp (val, "never"))
448 node->connectmode = conf_node::C_NEVER;
449 else if (!strcmp (val, "always"))
450 node->connectmode = conf_node::C_ALWAYS;
451 else if (!strcmp (val, "disabled"))
452 node->connectmode = conf_node::C_DISABLED;
453 else
454 return _("illegal value for 'connectmode', use one of 'ondemand', 'never', 'always' or 'disabled'. (ignored)");
455 }
456 else if (!strcmp (var, "inherit-tos"))
457 parse_bool (node->inherit_tos, "inherit-tos", true, false);
458 else if (!strcmp (var, "compress"))
459 parse_bool (node->compress, "compress", true, false);
460 // all these bool options really really cost a lot of executable size!
461 else if (!strcmp (var, "enable-tcp"))
462 {
463#if ENABLE_TCP
464 u8 v; parse_bool (v, "enable-tcp" , PROT_TCPv4, 0); node->protocols = (node->protocols & ~PROT_TCPv4) | v;
465#endif
466 }
467 else if (!strcmp (var, "enable-icmp"))
468 {
469#if ENABLE_ICMP
470 u8 v; parse_bool (v, "enable-icmp" , PROT_ICMPv4, 0); node->protocols = (node->protocols & ~PROT_ICMPv4) | v;
471#endif
472 }
473 else if (!strcmp (var, "enable-dns"))
474 {
475#if ENABLE_DNS
476 u8 v; parse_bool (v, "enable-dns" , PROT_DNSv4, 0); node->protocols = (node->protocols & ~PROT_DNSv4) | v;
477#endif
478 }
479 else if (!strcmp (var, "enable-udp"))
480 {
481 u8 v; parse_bool (v, "enable-udp" , PROT_UDPv4, 0); node->protocols = (node->protocols & ~PROT_UDPv4) | v;
482 }
483 else if (!strcmp (var, "enable-rawip"))
484 {
485 u8 v; parse_bool (v, "enable-rawip", PROT_IPv4, 0); node->protocols = (node->protocols & ~PROT_IPv4 ) | v;
486 }
487 else if (!strcmp (var, "allow-direct"))
488 node->allow_direct.push_back (strdup (val));
489 else if (!strcmp (var, "deny-direct"))
490 node->deny_direct.push_back (strdup (val));
491 else if (!strcmp (var, "max-ttl"))
492 node->max_ttl = atof (val);
493 else if (!strcmp (var, "max-queue"))
494 node->max_queue = atoi (val);
495
496 // unknown or misplaced
497 else
498 return _("unknown configuration directive - ignored");
499
500 return 0;
501}
502
503void
504conf_node::finalise ()
505{
506 if (max_queue < 1)
507 {
508 slog (L_WARN, _("%s: max-queue value invalid, setting it to 1."), nodename);
509 max_queue = 1;
510 }
511
512 if (routerprio > 1 && (connectmode != C_ALWAYS && connectmode != C_DISABLED))
513 {
514 //slog (L_WARN, _("%s: has non-zero router-priority but either 'never' or 'ondemand' as connectmode, setting it to 'always'."), nodename);
515 connectmode = C_ALWAYS;
516 }
517}
518
519void
520configuration_parser::parse_argv ()
521{
522 for (int i = 0; i < argc; ++i)
523 {
524 char *v = argv [i];
525
526 if (!*v)
527 continue;
528
529 char *enode = v;
530
531 while (*enode != '.' && *enode > ' ' && *enode != '=' && *enode)
532 enode++;
533
534 if (*enode != '.')
535 enode = 0;
536
537 char *wnode = node == &conf.default_node
538 ? 0
539 : node->nodename;
540
541 if ((!wnode && !enode)
542 || (wnode && enode && !strncmp (wnode, v, enode - v)))
543 {
544 const char *warn = parse_line (enode ? enode + 1 : v);
545
546 if (warn)
547 slog (L_WARN, _("%s, while parsing command line option '%s'."), warn, v);
548
549 *v = 0;
550 }
551 }
552}
553
554void
555configuration_parser::parse_file (const char *fname)
556{
557 if (FILE *f = fopen (fname, "r"))
558 {
147 char line[16384]; 559 char line [2048];
148 int lineno = 0; 560 int lineno = 0;
149 char *var, *val; 561 node = &conf.default_node;
150 conf_node *node = &default_node;
151 562
152 while (fgets (line, sizeof (line), f)) 563 while (fgets (line, sizeof (line), f))
153 { 564 {
154 lineno++; 565 lineno++;
155 566
156 { 567 const char *warn = parse_line (line);
157 char *end = line + strlen (line);
158 568
159 while (*end < ' ' && end >= line) 569 if (warn)
160 end--; 570 slog (L_WARN, _("%s, at '%s', line %d."), warn, fname, lineno);
161
162 *++end = 0;
163 }
164
165 char *tok = line;
166
167retry:
168 var = strtok (tok, "\t =");
169 tok = 0;
170
171 if (!var || !var[0])
172 continue; /* no tokens on this line */
173
174 if (var[0] == '#')
175 continue; /* comment: ignore */
176
177 val = strtok (NULL, "\t\n\r =");
178
179 if (!val || val[0] == '#')
180 {
181 slog (L_WARN,
182 _("no value for variable `%s', at '%s' line %d"),
183 var, fname, lineno);
184 break;
185 }
186
187 if (!strcmp (var, "on"))
188 {
189 if (!::thisnode
190 || (val[0] == '!' && strcmp (val + 1, ::thisnode))
191 || !strcmp (val, ::thisnode))
192 goto retry;
193
194 continue;
195 }
196
197 // truly global
198 if (!strcmp (var, "loglevel"))
199 {
200 loglevel l = string_to_loglevel (val);
201
202 if (l != L_NONE)
203 llevel = l;
204 else
205 slog (L_WARN, "'%s': %s, at '%s' line %d", val, UNKNOWN_LOGLEVEL, fname, line);
206 }
207 else if (!strcmp (var, "ip-proto"))
208 ip_proto = atoi (val);
209
210 // per config
211 else if (!strcmp (var, "node"))
212 {
213 default_node.id++;
214
215 node = new conf_node (default_node);
216
217 nodes.push_back (node);
218
219 node->nodename = strdup (val);
220
221 {
222 char *fname;
223 FILE *f;
224
225 asprintf (&fname, "%s/pubkey/%s", confbase, node->nodename);
226
227 f = fopen (fname, "r");
228 if (f)
229 {
230 node->rsa_key = RSA_new ();
231
232 if (!PEM_read_RSAPublicKey(f, &node->rsa_key, NULL, NULL))
233 {
234 ERR_load_RSA_strings (); ERR_load_PEM_strings ();
235 slog (L_ERR, _("unable to open public rsa key file '%s': %s"), fname, ERR_error_string (ERR_get_error (), 0));
236 exit (1);
237 }
238
239 RSA_blinding_on (node->rsa_key, 0);
240
241 fclose (f);
242 }
243 else
244 {
245 slog (need_keys ? L_ERR : L_NOTICE, _("unable to read public rsa key file '%s': %s"), fname, strerror (errno));
246
247 if (need_keys)
248 exit (1);
249 }
250
251 free (fname);
252 }
253
254 if (!::thisnode || !strcmp (node->nodename, ::thisnode))
255 thisnode = node;
256 }
257 else if (!strcmp (var, "private-key"))
258 prikeyfile = strdup (val);
259 else if (!strcmp (var, "ifpersist"))
260 {
261 parse_bool (ifpersist, "ifpersist", true, false);
262 }
263 else if (!strcmp (var, "ifname"))
264 ifname = strdup (val);
265 else if (!strcmp (var, "rekey"))
266 rekey = atoi (val);
267 else if (!strcmp (var, "keepalive"))
268 keepalive = atoi (val);
269 else if (!strcmp (var, "mtu"))
270 mtu = atoi (val);
271 else if (!strcmp (var, "if-up"))
272 script_if_up = strdup (val);
273 else if (!strcmp (var, "node-up"))
274 script_node_up = strdup (val);
275 else if (!strcmp (var, "node-down"))
276 script_node_down = strdup (val);
277
278 /* node-specific, non-defaultable */
279 else if (node != &default_node && !strcmp (var, "hostname"))
280 {
281 free (node->hostname);
282 node->hostname = strdup (val);
283 }
284
285 /* node-specific, defaultable */
286 else if (!strcmp (var, "udp-port"))
287 node->udp_port = atoi (val);
288 else if (!strcmp (var, "tcp-port"))
289 node->tcp_port = atoi (val);
290 else if (!strcmp (var, "router-priority"))
291 node->routerprio = atoi (val);
292 else if (!strcmp (var, "connect"))
293 {
294 if (!strcmp (val, "ondemand"))
295 node->connectmode = conf_node::C_ONDEMAND;
296 else if (!strcmp (val, "never"))
297 node->connectmode = conf_node::C_NEVER;
298 else if (!strcmp (val, "always"))
299 node->connectmode = conf_node::C_ALWAYS;
300 else if (!strcmp (val, "disabled"))
301 node->connectmode = conf_node::C_DISABLED;
302 else
303 slog (L_WARN,
304 _("illegal value for 'connectmode', use one of 'ondemand', 'never', 'always' or 'disabled', at '%s' line %d"),
305 var, fname, lineno);
306 }
307 else if (!strcmp (var, "inherit-tos"))
308 {
309 parse_bool (node->inherit_tos, "inherit-tos", true, false);
310 }
311 else if (!strcmp (var, "compress"))
312 {
313 parse_bool (node->compress, "compress", true, false);
314 }
315 // all these bool options really really cost a lot of executable size!
316 else if (!strcmp (var, "enable-tcp"))
317 {
318#if ENABLE_TCP
319 u8 v; parse_bool (v, "enable-tcp" , PROT_TCPv4, 0); node->protocols = (node->protocols & ~PROT_TCPv4) | v;
320#endif
321 }
322 else if (!strcmp (var, "enable-udp"))
323 {
324 u8 v; parse_bool (v, "enable-udp" , PROT_UDPv4, 0); node->protocols = (node->protocols & ~PROT_UDPv4) | v;
325 }
326 else if (!strcmp (var, "enable-rawip"))
327 {
328 u8 v; parse_bool (v, "enable-rawip", PROT_IPv4, 0); node->protocols = (node->protocols & ~PROT_IPv4 ) | v;
329 }
330
331 // unknown or misplaced
332 else
333 {
334 slog (L_WARN,
335 _("unknown or misplaced variable `%s', at '%s' line %d"),
336 var, fname, lineno);
337 }
338 } 571 }
339 572
340 fclose (f); 573 fclose (f);
574
575 parse_argv ();
341 } 576 }
342 else 577 else
343 { 578 {
344 slog (L_ERR, _("unable to read config file '%s': %s"), fname, strerror (errno)); 579 slog (L_ERR, _("unable to read config file '%s': %s"), fname, strerror (errno));
345 exit (1); 580 exit (EXIT_FAILURE);
346 } 581 }
582}
347 583
584configuration_parser::configuration_parser (configuration &conf,
585 bool need_keys,
586 int argc,
587 char **argv)
588: conf (conf),need_keys (need_keys), argc (argc), argv (argv)
589{
590 char *fname;
591
592 conf.clear ();
593
594 asprintf (&fname, "%s/gvpe.conf", confbase);
595 parse_file (fname);
348 free (fname); 596 free (fname);
349 597
350 fname = config_filename (prikeyfile, "hostkey"); 598 fname = conf.config_filename (conf.prikeyfile, "hostkey");
351 599
352 f = fopen (fname, "r"); 600 if (FILE *f = fopen (fname, "r"))
353 if (f)
354 { 601 {
355 rsa_key = RSA_new (); 602 conf.rsa_key = RSA_new ();
356 603
357 if (!PEM_read_RSAPrivateKey (f, &rsa_key, NULL, NULL)) 604 if (!PEM_read_RSAPrivateKey (f, &conf.rsa_key, NULL, NULL))
358 { 605 {
359 ERR_load_RSA_strings (); ERR_load_PEM_strings (); 606 ERR_load_RSA_strings (); ERR_load_PEM_strings ();
360 slog (L_ERR, _("unable to read private rsa key file '%s': %s"), fname, ERR_error_string (ERR_get_error (), 0)); 607 slog (L_ERR, _("unable to read private rsa key file '%s': %s"), fname, ERR_error_string (ERR_get_error (), 0));
361 exit (1); 608 exit (EXIT_FAILURE);
362 } 609 }
363 610
364 RSA_blinding_on (rsa_key, 0); 611 require (RSA_blinding_on (conf.rsa_key, 0));
365 612
366 fclose (f); 613 fclose (f);
367 } 614 }
368 else 615 else
369 { 616 {
370 slog (need_keys ? L_ERR : L_NOTICE, _("unable to open private rsa key file '%s': %s"), fname, strerror (errno)); 617 slog (need_keys ? L_ERR : L_NOTICE, _("unable to open private rsa key file '%s': %s"), fname, strerror (errno));
371 618
372 if (need_keys) 619 if (need_keys)
373 exit (1); 620 exit (EXIT_FAILURE);
374 } 621 }
375 622
376 free (fname); 623 free (fname);
377}
378 624
625 if (need_keys && ::thisnode
626 && conf.rsa_key && conf.thisnode && conf.thisnode->rsa_key)
627 if (BN_cmp (conf.rsa_key->n, conf.thisnode->rsa_key->n) != 0
628 || BN_cmp (conf.rsa_key->e, conf.thisnode->rsa_key->e) != 0)
629 {
630 slog (L_NOTICE, _("private hostkey and public node key mismatch: is '%s' the correct node?"), ::thisnode);
631 exit (EXIT_FAILURE);
632 }
633
634 for (configuration::node_vector::iterator i = conf.nodes.begin(); i != conf.nodes.end(); ++i)
635 (*i)->finalise ();
636}
637
638char *
379char *configuration::config_filename (const char *name, const char *dflt) 639configuration::config_filename (const char *name, const char *dflt)
380{ 640{
381 char *fname; 641 char *fname;
382 642
383 asprintf (&fname, name ? name : dflt, ::thisnode); 643 asprintf (&fname, name ? name : dflt, ::thisnode);
384 644
388 asprintf (&fname, "%s/%s", confbase, rname); 648 asprintf (&fname, "%s/%s", confbase, rname);
389 free (rname); 649 free (rname);
390 } 650 }
391 651
392 return fname; 652 return fname;
653}
654
655void
656conf_node::print ()
657{
658 printf ("%4d fe:fd:80:00:0%1x:%02x %c %-8.8s %-10.10s %02x %s%s%d\n",
659 id,
660 id >> 8, id & 0xff,
661 compress ? 'Y' : 'N',
662 connectmode == C_ONDEMAND ? "ondemand"
663 : connectmode == C_NEVER ? "never"
664 : connectmode == C_ALWAYS ? "always"
665 : connectmode == C_DISABLED ? "disabled"
666 : "",
667 nodename,
668 protocols,
669 hostname ? hostname : "",
670 hostname ? ":" : "",
671 hostname ? udp_port : 0
672 );
393} 673}
394 674
395void 675void
396configuration::print () 676configuration::print ()
397{ 677{
401 printf (_("MTU: %d\n"), mtu); 681 printf (_("MTU: %d\n"), mtu);
402 printf (_("rekeying interval: %d\n"), rekey); 682 printf (_("rekeying interval: %d\n"), rekey);
403 printf (_("keepalive interval: %d\n"), keepalive); 683 printf (_("keepalive interval: %d\n"), keepalive);
404 printf (_("interface: %s\n"), ifname); 684 printf (_("interface: %s\n"), ifname);
405 printf (_("primary rsa key: %s\n"), prikeyfile ? prikeyfile : "<default>"); 685 printf (_("primary rsa key: %s\n"), prikeyfile ? prikeyfile : "<default>");
406 printf (_("rsa key size: %d\n"), rsa_key ? RSA_size (rsa_key) : -1); 686 printf (_("rsa key size: %d\n"), rsa_key ? RSA_size (rsa_key) * 8 : -1);
407 printf ("\n"); 687 printf ("\n");
408 688
409 printf ("%4s %-17s %s %-8.8s %-10.10s %s\n", 689 printf ("%4s %-17s %s %-8.8s %-10.10s %04s %s\n",
410 _("ID#"), _("MAC"), _("Com"), _("Conmode"), _("Node"), _("Host:Port")); 690 _("ID#"), _("MAC"), _("Com"), _("Conmode"), _("Node"), _("Prot"), _("Host:Port"));
411 691
412 for (node_vector::iterator i = nodes.begin (); i != nodes.end (); ++i) 692 for (node_vector::iterator i = nodes.begin (); i != nodes.end (); ++i)
413 (*i)->print (); 693 (*i)->print ();
414 694
415 printf ("\n"); 695 printf ("\n");
416} 696}
417 697
418void 698configuration::configuration ()
419conf_node::print ()
420{ 699{
421 printf ("%4d fe:fd:80:00:0%1x:%02x %c %-8.8s %-10.10s %s%s%d\n", 700 asprintf (&confbase, "%s/gvpe", CONFDIR);
422 id,
423 id >> 8, id & 0xff,
424 compress ? 'Y' : 'N',
425 connectmode == C_ONDEMAND ? "ondemand" :
426 connectmode == C_NEVER ? "never" :
427 connectmode == C_ALWAYS ? "always" : "",
428 nodename,
429 hostname ? hostname : "",
430 hostname ? ":" : "",
431 hostname ? udp_port : 0
432 );
433}
434 701
702 init ();
703}
704
705configuration::~configuration ()
706{
707 cleanup ();
708}
709

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines