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.23 by pcg, Thu Jan 29 19:30:08 2004 UTC vs.
Revision 1.58 by root, Tue Jan 17 21:38:10 2012 UTC

1/* 1/*
2 conf.c -- configuration code 2 conf.C -- configuration code
3 Copyright (C) 2003-2004 Marc Lehmann <pcg@goof.com> 3 Copyright (C) 2003-2008,2011 Marc Lehmann <gvpe@schmorp.de>
4 4
5 This file is part of GVPE.
6
5 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
6 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
7 the Free Software Foundation; either version 2 of the License, or 9 Free Software Foundation; either version 3 of the License, or (at your
8 (at your option) any later version. 10 option) any later version.
9 11
10 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
11 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
13 GNU General Public License for more details. 15 Public License for more details.
14 16
15 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
16 along with this program; if not, write to the Free Software 18 with this program; if not, see <http://www.gnu.org/licenses/>.
17 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.
18*/ 30*/
19 31
20#include "config.h" 32#include "config.h"
21 33
22#include <cstdio> 34#include <cstdio>
35#include <openssl/pem.h> 47#include <openssl/pem.h>
36#include <openssl/rsa.h> 48#include <openssl/rsa.h>
37#include <openssl/rand.h> 49#include <openssl/rand.h>
38#include <openssl/bn.h> 50#include <openssl/bn.h>
39 51
40#include "gettext.h"
41
42#include "conf.h" 52#include "conf.h"
43#include "slog.h" 53#include "slog.h"
44#include "util.h" 54#include "util.h"
45 55
46char *confbase; 56char *confbase;
47char *thisnode; 57char *thisnode;
48char *identname; 58char *identname;
49char *pidfilename;
50 59
51struct configuration conf; 60struct configuration conf;
52 61
62u8
53u8 best_protocol (u8 protset) 63best_protocol (u8 protset)
54{ 64{
55 if (protset & PROT_IPv4 ) return PROT_IPv4; 65 if (protset & PROT_IPv4 ) return PROT_IPv4;
56 if (protset & PROT_ICMPv4) return PROT_ICMPv4; 66 if (protset & PROT_ICMPv4) return PROT_ICMPv4;
57 if (protset & PROT_UDPv4 ) return PROT_UDPv4; 67 if (protset & PROT_UDPv4 ) return PROT_UDPv4;
58 if (protset & PROT_TCPv4 ) return PROT_TCPv4; 68 if (protset & PROT_TCPv4 ) return PROT_TCPv4;
69 if (protset & PROT_DNSv4 ) return PROT_DNSv4;
59 70
60 return 0; 71 return 0;
61} 72}
62 73
74const char *
63const char *strprotocol (u8 protocol) 75strprotocol (u8 protocol)
64{ 76{
65 if (protocol & PROT_IPv4 ) return "rawip"; 77 if (protocol & PROT_IPv4 ) return "rawip";
66 if (protocol & PROT_ICMPv4) return "icmp"; 78 if (protocol & PROT_ICMPv4) return "icmp";
67 if (protocol & PROT_UDPv4 ) return "udp"; 79 if (protocol & PROT_UDPv4 ) return "udp";
68 if (protocol & PROT_TCPv4 ) return "tcp"; 80 if (protocol & PROT_TCPv4 ) return "tcp";
81 if (protocol & PROT_DNSv4 ) return "dns";
69 82
70 return "<unknown>"; 83 return "<unknown>";
71} 84}
72 85
73void 86static bool
74conf_node::print () 87match_list (const vector<const char *> &list, const char *str)
75{ 88{
76 printf ("%4d fe:fd:80:00:0%1x:%02x %c %-8.8s %-10.10s %s%s%d\n", 89 for (vector<const char *>::const_iterator i = list.end (); i-- > list.begin (); )
77 id, 90 if ((*i)[0] == '*' && !(*i)[1])
78 id >> 8, id & 0xff, 91 return true;
79 compress ? 'Y' : 'N', 92 else if (!strcmp (*i, str))
80 connectmode == C_ONDEMAND ? "ondemand" : 93 return true;
81 connectmode == C_NEVER ? "never" : 94
82 connectmode == C_ALWAYS ? "always" : "", 95 return false;
83 nodename, 96}
84 hostname ? hostname : "", 97
85 hostname ? ":" : "", 98bool
86 hostname ? udp_port : 0 99conf_node::may_direct (struct conf_node *other)
87 ); 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;
88} 108}
89 109
90conf_node::~conf_node () 110conf_node::~conf_node ()
91{ 111{
112#if 0
113 // does not work, because string pointers etc. are shared
114 // is not called, however
92 if (rsa_key) 115 if (rsa_key)
93 RSA_free (rsa_key); 116 RSA_free (rsa_key);
94 117
95 free (nodename); 118 free (nodename);
96 free (hostname); 119 free (hostname);
120 free (if_up_data);
121#if ENABLE_DNS
122 free (domain);
123 free (dns_hostname);
124#endif
125#endif
97} 126}
98 127
128void
99void configuration::init () 129configuration::init ()
100{ 130{
101 memset (this, 0, sizeof (*this)); 131 memset (this, 0, sizeof (*this));
102 132
103 mtu = DEFAULT_MTU; 133 mtu = DEFAULT_MTU;
134 nfmark = 0;
104 rekey = DEFAULT_REKEY; 135 rekey = DEFAULT_REKEY;
105 keepalive = DEFAULT_KEEPALIVE; 136 keepalive = DEFAULT_KEEPALIVE;
106 llevel = L_INFO; 137 llevel = L_INFO;
107 ip_proto = IPPROTO_GRE; 138 ip_proto = IPPROTO_GRE;
108#if ENABLE_ICMP 139#if ENABLE_ICMP
109 icmp_type = ICMP_ECHOREPLY; 140 icmp_type = ICMP_ECHOREPLY;
110#endif 141#endif
111 142
112 default_node.udp_port = DEFAULT_UDPPORT; 143 default_node.udp_port = DEFAULT_UDPPORT;
113 default_node.tcp_port = DEFAULT_UDPPORT; 144 default_node.tcp_port = DEFAULT_UDPPORT; // ehrm
114 default_node.connectmode = conf_node::C_ALWAYS; 145 default_node.connectmode = conf_node::C_ALWAYS;
115 default_node.compress = true; 146 default_node.compress = true;
116 default_node.protocols = PROT_UDPv4; 147 default_node.protocols = 0;
117} 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 ("");
118 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
119void configuration::cleanup() 169configuration::cleanup ()
120{ 170{
121 if (rsa_key) 171 if (rsa_key)
122 RSA_free (rsa_key); 172 RSA_free (rsa_key);
123 173
124 rsa_key = 0; 174 rsa_key = 0;
125 175
126 free (ifname); ifname = 0; 176 free (pidfilename); pidfilename = 0;
177 free (ifname); ifname = 0;
127#if ENABLE_HTTP_PROXY 178#if ENABLE_HTTP_PROXY
128 free (proxy_host); proxy_host = 0; 179 free (proxy_host); proxy_host = 0;
129 free (proxy_auth); proxy_auth = 0; 180 free (proxy_auth); proxy_auth = 0;
130#endif 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;
131} 189}
132 190
133void 191void
134configuration::clear_config () 192configuration::clear ()
135{ 193{
136 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)
137 delete *i; 195 delete *i;
138 196
139 nodes.clear (); 197 nodes.clear ();
140 198
141 cleanup (); 199 cleanup ();
142 init (); 200 init ();
143} 201}
144 202
203//static bool
204//is_true (const char *name)
205//{
206 //re
207//}
208
145#define parse_bool(target,name,trueval,falseval) \ 209#define parse_bool(target,name,trueval,falseval) do { \
146 if (!strcmp (val, "yes")) target = trueval; \ 210 if (!strcmp (val, "yes")) target = trueval; \
147 else if (!strcmp (val, "no")) target = falseval; \ 211 else if (!strcmp (val, "no")) target = falseval; \
148 else if (!strcmp (val, "true")) target = trueval; \ 212 else if (!strcmp (val, "true")) target = trueval; \
149 else if (!strcmp (val, "false")) target = falseval; \ 213 else if (!strcmp (val, "false")) target = falseval; \
150 else if (!strcmp (val, "on")) target = trueval; \ 214 else if (!strcmp (val, "on")) target = trueval; \
151 else if (!strcmp (val, "off")) target = falseval; \ 215 else if (!strcmp (val, "off")) target = falseval; \
152 else \ 216 else \
153 slog (L_WARN, \
154 _("illegal value for '%s', only 'yes|true|on' or 'no|false|off' allowed, at '%s' line %d"), \ 217 return _("illegal boolean value, only 'yes|true|on' or 'no|false|off' allowed, ignored"); \
155 name, var, fname, lineno); 218} while (0)
156 219
157void configuration::read_config (bool need_keys) 220const char *
221configuration_parser::parse_line (char *line)
158{ 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, ignored");
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 {
159 char *fname; 290 char *fname;
160 FILE *f; 291 FILE *f;
161 292
162 clear_config (); 293 asprintf (&fname, "%s/pubkey/%s", confbase, node->nodename);
163 294
164 asprintf (&fname, "%s/vped.conf", confbase);
165 f = fopen (fname, "r"); 295 f = fopen (fname, "r");
296 if (f)
297 {
298 node->rsa_key = RSA_new ();
166 299
167 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;
168 { 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 {
169 char line[16384]; 559 char line [2048];
170 int lineno = 0; 560 int lineno = 0;
171 char *var, *val;
172 conf_node *node = &default_node;
173 561
174 while (fgets (line, sizeof (line), f)) 562 while (fgets (line, sizeof (line), f))
175 { 563 {
176 lineno++; 564 lineno++;
177 565
178 { 566 const char *warn = parse_line (line);
179 char *end = line + strlen (line);
180 567
181 while (*end < ' ' && end >= line) 568 if (warn)
182 end--; 569 slog (L_WARN, _("%s, at '%s', line %d."), warn, fname, lineno);
183
184 *++end = 0;
185 }
186
187 char *tok = line;
188
189retry:
190 var = strtok (tok, "\t =");
191 tok = 0;
192
193 if (!var || !var[0])
194 continue; /* no tokens on this line */
195
196 if (var[0] == '#')
197 continue; /* comment: ignore */
198
199 val = strtok (NULL, "\t\n\r =");
200
201 if (!val || val[0] == '#')
202 {
203 slog (L_WARN,
204 _("no value for variable `%s', at '%s' line %d"),
205 var, fname, lineno);
206 break;
207 }
208
209 if (!strcmp (var, "on"))
210 {
211 if (!::thisnode
212 || (val[0] == '!' && strcmp (val + 1, ::thisnode))
213 || !strcmp (val, ::thisnode))
214 goto retry;
215
216 continue;
217 }
218
219 // truly global
220 if (!strcmp (var, "loglevel"))
221 {
222 loglevel l = string_to_loglevel (val);
223
224 if (l != L_NONE)
225 llevel = l;
226 else
227 slog (L_WARN, "'%s': %s, at '%s' line %d", val, UNKNOWN_LOGLEVEL, fname, line);
228 }
229 else if (!strcmp (var, "ip-proto"))
230 ip_proto = atoi (val);
231 else if (!strcmp (var, "icmp-type"))
232 {
233#if ENABLE_ICMP
234 icmp_type = atoi (val);
235#endif
236 }
237
238 // per config
239 else if (!strcmp (var, "node"))
240 {
241 default_node.id++;
242
243 node = new conf_node (default_node);
244
245 nodes.push_back (node);
246
247 node->nodename = strdup (val);
248
249 {
250 char *fname;
251 FILE *f;
252
253 asprintf (&fname, "%s/pubkey/%s", confbase, node->nodename);
254
255 f = fopen (fname, "r");
256 if (f)
257 {
258 node->rsa_key = RSA_new ();
259
260 if (!PEM_read_RSAPublicKey(f, &node->rsa_key, NULL, NULL))
261 {
262 ERR_load_RSA_strings (); ERR_load_PEM_strings ();
263 slog (L_ERR, _("unable to open public rsa key file '%s': %s"), fname, ERR_error_string (ERR_get_error (), 0));
264 exit (EXIT_FAILURE);
265 }
266
267 require (RSA_blinding_on (node->rsa_key, 0));
268
269 fclose (f);
270 }
271 else
272 {
273 slog (need_keys ? L_ERR : L_NOTICE, _("unable to read public rsa key file '%s': %s"), fname, strerror (errno));
274
275 if (need_keys)
276 exit (EXIT_FAILURE);
277 }
278
279 free (fname);
280 }
281
282 if (::thisnode && !strcmp (node->nodename, ::thisnode))
283 thisnode = node;
284 }
285 else if (!strcmp (var, "private-key"))
286 prikeyfile = strdup (val);
287 else if (!strcmp (var, "ifpersist"))
288 {
289 parse_bool (ifpersist, "ifpersist", true, false);
290 }
291 else if (!strcmp (var, "ifname"))
292 ifname = strdup (val);
293 else if (!strcmp (var, "rekey"))
294 rekey = atoi (val);
295 else if (!strcmp (var, "keepalive"))
296 keepalive = atoi (val);
297 else if (!strcmp (var, "mtu"))
298 mtu = atoi (val);
299 else if (!strcmp (var, "if-up"))
300 script_if_up = strdup (val);
301 else if (!strcmp (var, "node-up"))
302 script_node_up = strdup (val);
303 else if (!strcmp (var, "node-down"))
304 script_node_down = strdup (val);
305 else if (!strcmp (var, "http-proxy-host"))
306 {
307#if ENABLE_HTTP_PROXY
308 proxy_host = strdup (val);
309#endif
310 }
311 else if (!strcmp (var, "http-proxy-port"))
312 {
313#if ENABLE_HTTP_PROXY
314 proxy_port = atoi (val);
315#endif
316 }
317 else if (!strcmp (var, "http-proxy-auth"))
318 {
319#if ENABLE_HTTP_PROXY
320 proxy_auth = (char *)base64_encode ((const u8 *)val, strlen (val));
321#endif
322 }
323
324 /* node-specific, non-defaultable */
325 else if (node != &default_node && !strcmp (var, "hostname"))
326 {
327 free (node->hostname);
328 node->hostname = strdup (val);
329 }
330
331 /* node-specific, defaultable */
332 else if (!strcmp (var, "udp-port"))
333 node->udp_port = atoi (val);
334 else if (!strcmp (var, "tcp-port"))
335 node->tcp_port = atoi (val);
336 else if (!strcmp (var, "router-priority"))
337 node->routerprio = atoi (val);
338 else if (!strcmp (var, "connect"))
339 {
340 if (!strcmp (val, "ondemand"))
341 node->connectmode = conf_node::C_ONDEMAND;
342 else if (!strcmp (val, "never"))
343 node->connectmode = conf_node::C_NEVER;
344 else if (!strcmp (val, "always"))
345 node->connectmode = conf_node::C_ALWAYS;
346 else if (!strcmp (val, "disabled"))
347 node->connectmode = conf_node::C_DISABLED;
348 else
349 slog (L_WARN,
350 _("illegal value for 'connectmode', use one of 'ondemand', 'never', 'always' or 'disabled', at '%s' line %d"),
351 var, fname, lineno);
352 }
353 else if (!strcmp (var, "inherit-tos"))
354 {
355 parse_bool (node->inherit_tos, "inherit-tos", true, false);
356 }
357 else if (!strcmp (var, "compress"))
358 {
359 parse_bool (node->compress, "compress", true, false);
360 }
361 // all these bool options really really cost a lot of executable size!
362 else if (!strcmp (var, "enable-tcp"))
363 {
364#if ENABLE_TCP
365 u8 v; parse_bool (v, "enable-tcp" , PROT_TCPv4, 0); node->protocols = (node->protocols & ~PROT_TCPv4) | v;
366#endif
367 }
368 else if (!strcmp (var, "enable-icmp"))
369 {
370#if ENABLE_ICMP
371 u8 v; parse_bool (v, "enable-icmp" , PROT_ICMPv4, 0); node->protocols = (node->protocols & ~PROT_ICMPv4) | v;
372#endif
373 }
374 else if (!strcmp (var, "enable-udp"))
375 {
376 u8 v; parse_bool (v, "enable-udp" , PROT_UDPv4, 0); node->protocols = (node->protocols & ~PROT_UDPv4) | v;
377 }
378 else if (!strcmp (var, "enable-rawip"))
379 {
380 u8 v; parse_bool (v, "enable-rawip", PROT_IPv4, 0); node->protocols = (node->protocols & ~PROT_IPv4 ) | v;
381 }
382
383 // unknown or misplaced
384 else
385 slog (L_WARN,
386 _("unknown or misplaced variable `%s', at '%s' line %d"),
387 var, fname, lineno);
388 } 570 }
389 571
390 fclose (f); 572 fclose (f);
573
574 parse_argv ();
391 } 575 }
392 else 576 else
393 { 577 {
394 slog (L_ERR, _("unable to read config file '%s': %s"), fname, strerror (errno)); 578 slog (L_ERR, _("unable to read config file '%s': %s"), fname, strerror (errno));
395 exit (EXIT_FAILURE); 579 exit (EXIT_FAILURE);
396 } 580 }
581}
397 582
583configuration_parser::configuration_parser (configuration &conf,
584 bool need_keys,
585 int argc,
586 char **argv)
587: conf (conf),need_keys (need_keys), argc (argc), argv (argv)
588{
589 char *fname;
590
591 conf.clear ();
592 node = &conf.default_node;
593
594 asprintf (&fname, "%s/gvpe.conf", confbase);
595 parse_file (fname);
398 free (fname); 596 free (fname);
399 597
400 fname = config_filename (prikeyfile, "hostkey"); 598 fname = conf.config_filename (conf.prikeyfile, "hostkey");
401 599
402 f = fopen (fname, "r"); 600 if (FILE *f = fopen (fname, "r"))
403 if (f)
404 { 601 {
405 rsa_key = RSA_new (); 602 conf.rsa_key = RSA_new ();
406 603
407 if (!PEM_read_RSAPrivateKey (f, &rsa_key, NULL, NULL)) 604 if (!PEM_read_RSAPrivateKey (f, &conf.rsa_key, NULL, NULL))
408 { 605 {
409 ERR_load_RSA_strings (); ERR_load_PEM_strings (); 606 ERR_load_RSA_strings (); ERR_load_PEM_strings ();
410 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));
411 exit (EXIT_FAILURE); 608 exit (EXIT_FAILURE);
412 } 609 }
413 610
414 require (RSA_blinding_on (rsa_key, 0)); 611 require (RSA_blinding_on (conf.rsa_key, 0));
415 612
416 fclose (f); 613 fclose (f);
417 } 614 }
418 else 615 else
419 { 616 {
421 618
422 if (need_keys) 619 if (need_keys)
423 exit (EXIT_FAILURE); 620 exit (EXIT_FAILURE);
424 } 621 }
425 622
623 free (fname);
624
426 if (need_keys && ::thisnode 625 if (need_keys && ::thisnode
427 && rsa_key && thisnode && thisnode->rsa_key) 626 && conf.rsa_key && conf.thisnode && conf.thisnode->rsa_key)
428 if (BN_cmp (rsa_key->n, thisnode->rsa_key->n) != 0 627 if (BN_cmp (conf.rsa_key->n, conf.thisnode->rsa_key->n) != 0
429 || BN_cmp (rsa_key->e, thisnode->rsa_key->e) != 0) 628 || BN_cmp (conf.rsa_key->e, conf.thisnode->rsa_key->e) != 0)
430 { 629 {
431 slog (L_NOTICE, _("private hostkey and public node key mismatch: is '%s' the correct node?"), ::thisnode); 630 slog (L_NOTICE, _("private hostkey and public node key mismatch: is '%s' the correct node?"), ::thisnode);
432 exit (EXIT_FAILURE); 631 exit (EXIT_FAILURE);
433 } 632 }
434 633
435 free (fname); 634 for (configuration::node_vector::iterator i = conf.nodes.begin(); i != conf.nodes.end(); ++i)
635 (*i)->finalise ();
436} 636}
437 637
638char *
438char *configuration::config_filename (const char *name, const char *dflt) 639configuration::config_filename (const char *name, const char *dflt)
439{ 640{
440 char *fname; 641 char *fname;
441 642
442 asprintf (&fname, name ? name : dflt, ::thisnode); 643 asprintf (&fname, name ? name : dflt, ::thisnode);
443 644
447 asprintf (&fname, "%s/%s", confbase, rname); 648 asprintf (&fname, "%s/%s", confbase, rname);
448 free (rname); 649 free (rname);
449 } 650 }
450 651
451 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 );
452} 673}
453 674
454void 675void
455configuration::print () 676configuration::print ()
456{ 677{
463 printf (_("interface: %s\n"), ifname); 684 printf (_("interface: %s\n"), ifname);
464 printf (_("primary rsa key: %s\n"), prikeyfile ? prikeyfile : "<default>"); 685 printf (_("primary rsa key: %s\n"), prikeyfile ? prikeyfile : "<default>");
465 printf (_("rsa key size: %d\n"), rsa_key ? RSA_size (rsa_key) * 8 : -1); 686 printf (_("rsa key size: %d\n"), rsa_key ? RSA_size (rsa_key) * 8 : -1);
466 printf ("\n"); 687 printf ("\n");
467 688
468 printf ("%4s %-17s %s %-8.8s %-10.10s %s\n", 689 printf ("%4s %-17s %s %-8.8s %-10.10s %04s %s\n",
469 _("ID#"), _("MAC"), _("Com"), _("Conmode"), _("Node"), _("Host:Port")); 690 _("ID#"), _("MAC"), _("Com"), _("Conmode"), _("Node"), _("Prot"), _("Host:Port"));
470 691
471 for (node_vector::iterator i = nodes.begin (); i != nodes.end (); ++i) 692 for (node_vector::iterator i = nodes.begin (); i != nodes.end (); ++i)
472 (*i)->print (); 693 (*i)->print ();
473 694
474 printf ("\n"); 695 printf ("\n");
475} 696}
476 697
477configuration::configuration () 698configuration::configuration ()
478{ 699{
700 asprintf (&confbase, "%s/gvpe", CONFDIR);
701
479 init (); 702 init ();
480} 703}
481 704
482configuration::~configuration () 705configuration::~configuration ()
483{ 706{
484 cleanup (); 707 cleanup ();
485} 708}
486 709
487

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines