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.43 by pcg, Thu Aug 7 16:34:21 2008 UTC vs.
Revision 1.56 by root, Sun Mar 6 21:01:36 2011 UTC

1/* 1/*
2 conf.c -- configuration code 2 conf.C -- configuration code
3 Copyright (C) 2003-2005 Marc Lehmann <gvpe@schmorp.de> 3 Copyright (C) 2003-2008,2011 Marc Lehmann <gvpe@schmorp.de>
4 4
5 This file is part of GVPE. 5 This file is part of GVPE.
6 6
7 GVPE is free software; you can redistribute it and/or modify 7 GVPE is free software; you can redistribute it and/or modify it
8 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
9 the Free Software Foundation; either version 2 of the License, or 9 Free Software Foundation; either version 3 of the License, or (at your
10 (at your option) any later version. 10 option) any later version.
11 11
12 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
13 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15 GNU General Public License for more details. 15 Public License for more details.
16 16
17 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
18 along with gvpe; if not, write to the Free Software 18 with this program; if not, see <http://www.gnu.org/licenses/>.
19 Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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.
20*/ 30*/
21 31
22#include "config.h" 32#include "config.h"
23 33
24#include <cstdio> 34#include <cstdio>
47char *thisnode; 57char *thisnode;
48char *identname; 58char *identname;
49 59
50struct configuration conf; 60struct configuration conf;
51 61
62u8
52u8 best_protocol (u8 protset) 63best_protocol (u8 protset)
53{ 64{
54 if (protset & PROT_IPv4 ) return PROT_IPv4; 65 if (protset & PROT_IPv4 ) return PROT_IPv4;
55 if (protset & PROT_ICMPv4) return PROT_ICMPv4; 66 if (protset & PROT_ICMPv4) return PROT_ICMPv4;
56 if (protset & PROT_UDPv4 ) return PROT_UDPv4; 67 if (protset & PROT_UDPv4 ) return PROT_UDPv4;
57 if (protset & PROT_TCPv4 ) return PROT_TCPv4; 68 if (protset & PROT_TCPv4 ) return PROT_TCPv4;
58 if (protset & PROT_DNSv4 ) return PROT_DNSv4; 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";
82 94
83 return false; 95 return false;
84} 96}
85 97
86bool 98bool
87conf_node::can_direct (struct conf_node *other) 99conf_node::may_direct (struct conf_node *other)
88{ 100{
89 if (match_list (allow_direct, other->nodename)) 101 if (match_list (allow_direct, other->nodename))
90 return true; 102 return true;
91 103
92 if (match_list (deny_direct, other->nodename)) 104 if (match_list (deny_direct, other->nodename))
93 return false; 105 return false;
94 106
95 return true; 107 return true;
96}
97
98void
99conf_node::print ()
100{
101 printf ("%4d fe:fd:80:00:0%1x:%02x %c %-8.8s %-10.10s %s%s%d\n",
102 id,
103 id >> 8, id & 0xff,
104 compress ? 'Y' : 'N',
105 connectmode == C_ONDEMAND ? "ondemand" :
106 connectmode == C_NEVER ? "never" :
107 connectmode == C_ALWAYS ? "always" : "",
108 nodename,
109 hostname ? hostname : "",
110 hostname ? ":" : "",
111 hostname ? udp_port : 0
112 );
113} 108}
114 109
115conf_node::~conf_node () 110conf_node::~conf_node ()
116{ 111{
117#if 0 112#if 0
128 free (dns_hostname); 123 free (dns_hostname);
129#endif 124#endif
130#endif 125#endif
131} 126}
132 127
128void
133void configuration::init () 129configuration::init ()
134{ 130{
135 memset (this, 0, sizeof (*this)); 131 memset (this, 0, sizeof (*this));
136 132
137 mtu = DEFAULT_MTU; 133 mtu = DEFAULT_MTU;
134 nfmark = 0;
138 rekey = DEFAULT_REKEY; 135 rekey = DEFAULT_REKEY;
139 keepalive = DEFAULT_KEEPALIVE; 136 keepalive = DEFAULT_KEEPALIVE;
140 llevel = L_INFO; 137 llevel = L_INFO;
141 ip_proto = IPPROTO_GRE; 138 ip_proto = IPPROTO_GRE;
142#if ENABLE_ICMP 139#if ENABLE_ICMP
154 default_node.if_up_data = strdup (""); 151 default_node.if_up_data = strdup ("");
155 152
156#if ENABLE_DNS 153#if ENABLE_DNS
157 default_node.dns_port = 0; // default is 0 == client 154 default_node.dns_port = 0; // default is 0 == client
158 155
156 dns_case_preserving = true;
159 dns_forw_host = strdup ("127.0.0.1"); 157 dns_forw_host = strdup ("127.0.0.1");
160 dns_forw_port = 53; 158 dns_forw_port = 53;
161 dns_timeout_factor = DEFAULT_DNS_TIMEOUT_FACTOR; 159 dns_timeout_factor = DEFAULT_DNS_TIMEOUT_FACTOR;
162 dns_send_interval = DEFAULT_DNS_SEND_INTERVAL; 160 dns_send_interval = DEFAULT_DNS_SEND_INTERVAL;
163 dns_overlap_factor = DEFAULT_DNS_OVERLAP_FACTOR; 161 dns_overlap_factor = DEFAULT_DNS_OVERLAP_FACTOR;
165#endif 163#endif
166 164
167 conf.pidfilename = strdup (LOCALSTATEDIR "/run/gvpe.pid"); 165 conf.pidfilename = strdup (LOCALSTATEDIR "/run/gvpe.pid");
168} 166}
169 167
168void
170void configuration::cleanup() 169configuration::cleanup ()
171{ 170{
172 if (rsa_key) 171 if (rsa_key)
173 RSA_free (rsa_key); 172 RSA_free (rsa_key);
174 173
175 rsa_key = 0; 174 rsa_key = 0;
176 175
177 free (pidfilename); pidfilename = 0; 176 free (pidfilename); pidfilename = 0;
178 free (ifname); ifname = 0; 177 free (ifname); ifname = 0;
179#if ENABLE_HTTP_PROXY 178#if ENABLE_HTTP_PROXY
180 free (proxy_host); proxy_host = 0; 179 free (proxy_host); proxy_host = 0;
181 free (proxy_auth); proxy_auth = 0; 180 free (proxy_auth); proxy_auth = 0;
182#endif 181#endif
183#if ENABLE_DNS 182#if ENABLE_DNS
184 free (dns_forw_host); dns_forw_host = 0; 183 free (dns_forw_host); dns_forw_host = 0;
185#endif 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;
186} 189}
187 190
188void 191void
189configuration::clear () 192configuration::clear ()
190{ 193{
194 nodes.clear (); 197 nodes.clear ();
195 198
196 cleanup (); 199 cleanup ();
197 init (); 200 init ();
198} 201}
202
203//static bool
204//is_true (const char *name)
205//{
206 //re
207//}
199 208
200#define parse_bool(target,name,trueval,falseval) do { \ 209#define parse_bool(target,name,trueval,falseval) do { \
201 if (!strcmp (val, "yes")) target = trueval; \ 210 if (!strcmp (val, "yes")) target = trueval; \
202 else if (!strcmp (val, "no")) target = falseval; \ 211 else if (!strcmp (val, "no")) target = falseval; \
203 else if (!strcmp (val, "true")) target = trueval; \ 212 else if (!strcmp (val, "true")) target = trueval; \
204 else if (!strcmp (val, "false")) target = falseval; \ 213 else if (!strcmp (val, "false")) target = falseval; \
205 else if (!strcmp (val, "on")) target = trueval; \ 214 else if (!strcmp (val, "on")) target = trueval; \
206 else if (!strcmp (val, "off")) target = falseval; \ 215 else if (!strcmp (val, "off")) target = falseval; \
207 else \ 216 else \
208 return _("illegal boolean value, only 'yes|true|on' or 'no|false|off' allowed. (ignored)"); \ 217 return _("illegal boolean value, only 'yes|true|on' or 'no|false|off' allowed, ignored"); \
209} while (0) 218} while (0)
210 219
211const char * 220const char *
212configuration_parser::parse_line (char *line) 221configuration_parser::parse_line (char *line)
213{ 222{
231 return 0; /* comment: ignore */ 240 return 0; /* comment: ignore */
232 241
233 char *val = strtok (NULL, "\t\n\r ="); 242 char *val = strtok (NULL, "\t\n\r =");
234 243
235 if (!val || val[0] == '#') 244 if (!val || val[0] == '#')
236 return _("no value given for variable. (ignored)"); 245 return _("no value given for variable, ignored");
237 246
238 if (!strcmp (var, "on")) 247 else if (!strcmp (var, "on"))
239 { 248 {
240 if (!::thisnode 249 if (::thisnode
241 || (val[0] == '!' && strcmp (val + 1, ::thisnode)) 250 && ((val[0] == '!' && strcmp (val + 1, ::thisnode))
242 || !strcmp (val, ::thisnode)) 251 || !strcmp (val, ::thisnode)))
243 return parse_line (strtok (NULL, "\n\r")); 252 return parse_line (strtok (NULL, "\n\r"));
244 else 253 }
245 return 0; 254
255 else if (!strcmp (var, "include"))
256 {
257 char *fname = conf.config_filename (val);
258 parse_file (fname);
259 free (fname);
246 } 260 }
247 261
248 // truly global 262 // truly global
249 if (!strcmp (var, "loglevel")) 263 else if (!strcmp (var, "loglevel"))
250 { 264 {
251 loglevel l = string_to_loglevel (val); 265 loglevel l = string_to_loglevel (val);
252 266
253 if (l == L_NONE) 267 if (l == L_NONE)
254 return _("unknown loglevel. (skipping)"); 268 return _("unknown loglevel, ignored");
255 } 269 }
256 else if (!strcmp (var, "ip-proto")) 270 else if (!strcmp (var, "ip-proto"))
257 conf.ip_proto = atoi (val); 271 conf.ip_proto = atoi (val);
258 else if (!strcmp (var, "icmp-type")) 272 else if (!strcmp (var, "icmp-type"))
259 { 273 {
318 conf.rekey = atoi (val); 332 conf.rekey = atoi (val);
319 else if (!strcmp (var, "keepalive")) 333 else if (!strcmp (var, "keepalive"))
320 conf.keepalive = atoi (val); 334 conf.keepalive = atoi (val);
321 else if (!strcmp (var, "mtu")) 335 else if (!strcmp (var, "mtu"))
322 conf.mtu = atoi (val); 336 conf.mtu = atoi (val);
337 else if (!strcmp (var, "nfmark"))
338 conf.nfmark = atoi (val);
323 else if (!strcmp (var, "if-up")) 339 else if (!strcmp (var, "if-up"))
324 free (conf.script_if_up), conf.script_if_up = strdup (val); 340 free (conf.script_if_up), conf.script_if_up = strdup (val);
325 else if (!strcmp (var, "node-up")) 341 else if (!strcmp (var, "node-up"))
326 free (conf.script_node_up), conf.script_node_up = strdup (val); 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);
327 else if (!strcmp (var, "node-down")) 345 else if (!strcmp (var, "node-down"))
328 free (conf.script_node_down), conf.script_node_down = strdup (val); 346 free (conf.script_node_down), conf.script_node_down = strdup (val);
329 else if (!strcmp (var, "pid-file")) 347 else if (!strcmp (var, "pid-file"))
330 free (conf.pidfilename), conf.pidfilename = strdup (val); 348 free (conf.pidfilename), conf.pidfilename = strdup (val);
331 else if (!strcmp (var, "dns-forw-host")) 349 else if (!strcmp (var, "dns-forw-host"))
360 } 378 }
361 else if (!strcmp (var, "dns-max-outstanding")) 379 else if (!strcmp (var, "dns-max-outstanding"))
362 { 380 {
363#if ENABLE_DNS 381#if ENABLE_DNS
364 conf.dns_max_outstanding = atoi (val); 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);
365#endif 389#endif
366 } 390 }
367 else if (!strcmp (var, "http-proxy-host")) 391 else if (!strcmp (var, "http-proxy-host"))
368 { 392 {
369#if ENABLE_HTTP_PROXY 393#if ENABLE_HTTP_PROXY
425 else if (!strcmp (val, "always")) 449 else if (!strcmp (val, "always"))
426 node->connectmode = conf_node::C_ALWAYS; 450 node->connectmode = conf_node::C_ALWAYS;
427 else if (!strcmp (val, "disabled")) 451 else if (!strcmp (val, "disabled"))
428 node->connectmode = conf_node::C_DISABLED; 452 node->connectmode = conf_node::C_DISABLED;
429 else 453 else
430 return _("illegal value for 'connectmode', use one of 'ondemand', 'never', 'always' or 'disabled'. (ignored)"); 454 return _("illegal value for 'connectmode', use one of 'ondemand', 'never', 'always' or 'disabled', ignored");
431 } 455 }
432 else if (!strcmp (var, "inherit-tos")) 456 else if (!strcmp (var, "inherit-tos"))
433 parse_bool (node->inherit_tos, "inherit-tos", true, false); 457 parse_bool (node->inherit_tos, "inherit-tos", true, false);
434 else if (!strcmp (var, "compress")) 458 else if (!strcmp (var, "compress"))
435 parse_bool (node->compress, "compress", true, false); 459 parse_bool (node->compress, "compress", true, false);
469 else if (!strcmp (var, "max-queue")) 493 else if (!strcmp (var, "max-queue"))
470 node->max_queue = atoi (val); 494 node->max_queue = atoi (val);
471 495
472 // unknown or misplaced 496 // unknown or misplaced
473 else 497 else
474 return _("unknown configuration directive. (ignored)"); 498 return _("unknown configuration directive - ignored");
475 499
476 return 0; 500 return 0;
477} 501}
478 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
479void configuration_parser::parse_argv () 520configuration_parser::parse_argv ()
480{ 521{
481 for (int i = 0; i < argc; ++i) 522 for (int i = 0; i < argc; ++i)
482 { 523 {
483 char *v = argv [i]; 524 char *v = argv [i];
484 525
505 if (warn) 546 if (warn)
506 slog (L_WARN, _("%s, while parsing command line option '%s'."), warn, v); 547 slog (L_WARN, _("%s, while parsing command line option '%s'."), warn, v);
507 548
508 *v = 0; 549 *v = 0;
509 } 550 }
551 }
552}
553
554void
555configuration_parser::parse_file (const char *fname)
556{
557 if (FILE *f = fopen (fname, "r"))
558 {
559 char line [2048];
560 int lineno = 0;
561
562 while (fgets (line, sizeof (line), f))
563 {
564 lineno++;
565
566 const char *warn = parse_line (line);
567
568 if (warn)
569 slog (L_WARN, _("%s, at '%s', line %d."), warn, fname, lineno);
570 }
571
572 fclose (f);
573
574 parse_argv ();
575 }
576 else
577 {
578 slog (L_ERR, _("unable to read config file '%s': %s"), fname, strerror (errno));
579 exit (EXIT_FAILURE);
510 } 580 }
511} 581}
512 582
513configuration_parser::configuration_parser (configuration &conf, 583configuration_parser::configuration_parser (configuration &conf,
514 bool need_keys, 584 bool need_keys,
515 int argc, 585 int argc,
516 char **argv) 586 char **argv)
517: conf (conf),need_keys (need_keys), argc (argc), argv (argv) 587: conf (conf),need_keys (need_keys), argc (argc), argv (argv)
518{ 588{
519 char *fname; 589 char *fname;
520 FILE *f;
521 590
522 conf.clear (); 591 conf.clear ();
592 node = &conf.default_node;
523 593
524 asprintf (&fname, "%s/gvpe.conf", confbase); 594 asprintf (&fname, "%s/gvpe.conf", confbase);
525 f = fopen (fname, "r"); 595 parse_file (fname);
526
527 if (f)
528 {
529 char line[16384];
530 int lineno = 0;
531 node = &conf.default_node;
532
533 while (fgets (line, sizeof (line), f))
534 {
535 lineno++;
536
537 const char *warn = parse_line (line);
538
539 if (warn)
540 slog (L_WARN, _("%s, at '%s', line %d."), warn, fname, lineno);
541 }
542
543 fclose (f);
544
545 parse_argv ();
546 }
547 else
548 {
549 slog (L_ERR, _("unable to read config file '%s': %s"), fname, strerror (errno));
550 exit (EXIT_FAILURE);
551 }
552
553 free (fname); 596 free (fname);
554 597
555 fname = conf.config_filename (conf.prikeyfile, "hostkey"); 598 fname = conf.config_filename (conf.prikeyfile, "hostkey");
556 599
557 f = fopen (fname, "r"); 600 if (FILE *f = fopen (fname, "r"))
558 if (f)
559 { 601 {
560 conf.rsa_key = RSA_new (); 602 conf.rsa_key = RSA_new ();
561 603
562 if (!PEM_read_RSAPrivateKey (f, &conf.rsa_key, NULL, NULL)) 604 if (!PEM_read_RSAPrivateKey (f, &conf.rsa_key, NULL, NULL))
563 { 605 {
575 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));
576 618
577 if (need_keys) 619 if (need_keys)
578 exit (EXIT_FAILURE); 620 exit (EXIT_FAILURE);
579 } 621 }
622
623 free (fname);
580 624
581 if (need_keys && ::thisnode 625 if (need_keys && ::thisnode
582 && conf.rsa_key && conf.thisnode && conf.thisnode->rsa_key) 626 && conf.rsa_key && conf.thisnode && conf.thisnode->rsa_key)
583 if (BN_cmp (conf.rsa_key->n, conf.thisnode->rsa_key->n) != 0 627 if (BN_cmp (conf.rsa_key->n, conf.thisnode->rsa_key->n) != 0
584 || BN_cmp (conf.rsa_key->e, conf.thisnode->rsa_key->e) != 0) 628 || BN_cmp (conf.rsa_key->e, conf.thisnode->rsa_key->e) != 0)
585 { 629 {
586 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);
587 exit (EXIT_FAILURE); 631 exit (EXIT_FAILURE);
588 } 632 }
589 633
590 free (fname); 634 for (configuration::node_vector::iterator i = conf.nodes.begin(); i != conf.nodes.end(); ++i)
635 (*i)->finalise ();
591} 636}
592 637
638char *
593char *configuration::config_filename (const char *name, const char *dflt) 639configuration::config_filename (const char *name, const char *dflt)
594{ 640{
595 char *fname; 641 char *fname;
596 642
597 asprintf (&fname, name ? name : dflt, ::thisnode); 643 asprintf (&fname, name ? name : dflt, ::thisnode);
598 644
602 asprintf (&fname, "%s/%s", confbase, rname); 648 asprintf (&fname, "%s/%s", confbase, rname);
603 free (rname); 649 free (rname);
604 } 650 }
605 651
606 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 );
607} 673}
608 674
609void 675void
610configuration::print () 676configuration::print ()
611{ 677{
618 printf (_("interface: %s\n"), ifname); 684 printf (_("interface: %s\n"), ifname);
619 printf (_("primary rsa key: %s\n"), prikeyfile ? prikeyfile : "<default>"); 685 printf (_("primary rsa key: %s\n"), prikeyfile ? prikeyfile : "<default>");
620 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);
621 printf ("\n"); 687 printf ("\n");
622 688
623 printf ("%4s %-17s %s %-8.8s %-10.10s %s\n", 689 printf ("%4s %-17s %s %-8.8s %-10.10s %04s %s\n",
624 _("ID#"), _("MAC"), _("Com"), _("Conmode"), _("Node"), _("Host:Port")); 690 _("ID#"), _("MAC"), _("Com"), _("Conmode"), _("Node"), _("Prot"), _("Host:Port"));
625 691
626 for (node_vector::iterator i = nodes.begin (); i != nodes.end (); ++i) 692 for (node_vector::iterator i = nodes.begin (); i != nodes.end (); ++i)
627 (*i)->print (); 693 (*i)->print ();
628 694
629 printf ("\n"); 695 printf ("\n");
639configuration::~configuration () 705configuration::~configuration ()
640{ 706{
641 cleanup (); 707 cleanup ();
642} 708}
643 709
644

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines