ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/gvpe.C
Revision: 1.25
Committed: Tue Jul 16 16:44:36 2013 UTC (10 years, 10 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.24: +9 -0 lines
Log Message:
3.x

File Contents

# User Rev Content
1 pcg 1.1 /*
2 pcg 1.4 gvpe.C -- the main file for gvpe
3 pcg 1.1 Copyright (C) 1998-2002 Ivo Timmermans <ivo@o2w.nl>
4     2000-2002 Guus Sliepen <guus@sliepen.eu.org>
5 root 1.24 2003-2013 Marc Lehmann <gvpe@schmorp.de>
6 pcg 1.1
7     This file is part of GVPE.
8    
9 pcg 1.13 GVPE is free software; you can redistribute it and/or modify it
10     under the terms of the GNU General Public License as published by the
11     Free Software Foundation; either version 3 of the License, or (at your
12     option) any later version.
13    
14     This program is distributed in the hope that it will be useful, but
15     WITHOUT ANY WARRANTY; without even the implied warranty of
16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17     Public License for more details.
18    
19     You should have received a copy of the GNU General Public License along
20     with this program; if not, see <http://www.gnu.org/licenses/>.
21    
22     Additional permission under GNU GPL version 3 section 7
23    
24     If you modify this Program, or any covered work, by linking or
25     combining it with the OpenSSL project's OpenSSL library (or a modified
26     version of that library), containing parts covered by the terms of the
27     OpenSSL or SSLeay licenses, the licensors of this Program grant you
28     additional permission to convey the resulting work. Corresponding
29     Source for a non-source form of such a combination shall include the
30     source code for the parts of OpenSSL used as well as that of the
31     covered work.
32 pcg 1.1 */
33    
34     #include "config.h"
35    
36     #include <cstdio>
37     #include <cstring>
38     #include <cstdlib>
39    
40     #include <errno.h>
41     #include <fcntl.h>
42     #include <getopt.h>
43     #include <signal.h>
44     #include <sys/types.h>
45 root 1.24 #include <sys/stat.h>
46 pcg 1.1 #include <unistd.h>
47     #include <signal.h>
48     #include <termios.h>
49    
50     #if HAVE_SYS_MMAN_H
51     # include <sys/mman.h>
52     #endif
53    
54     #include <openssl/err.h>
55     #include <openssl/rand.h>
56    
57 pcg 1.2 #include "gettext.h"
58 pcg 1.1 #include "pidfile.h"
59    
60     #include "conf.h"
61     #include "slog.h"
62     #include "util.h"
63     #include "vpn.h"
64 pcg 1.10 #include "ev_cpp.h"
65 root 1.25 #include "hkdf.h"
66 pcg 1.1
67     static loglevel llevel = L_NONE;
68    
69     /* If nonzero, display usage information and exit. */
70     static int show_help;
71    
72     /* If nonzero, print the version on standard output and exit. */
73     static int show_version;
74    
75     /* If nonzero, disable swapping for this process. */
76     static int do_mlock = 0;
77    
78     /* If zero, don't detach from the terminal. */
79     static int do_detach = 1;
80    
81     static struct option const long_options[] =
82 root 1.18 {
83     {"config", required_argument, NULL, 'c'},
84     {"help", no_argument, &show_help, 1},
85     {"version", no_argument, &show_version, 1},
86     {"no-detach", no_argument, &do_detach, 0},
87     {"log-level", required_argument, NULL, 'l'},
88     {"mlock", no_argument, &do_mlock, 1},
89     {NULL, 0, NULL, 0}
90     };
91 pcg 1.1
92     static void
93     usage (int status)
94     {
95     if (status != 0)
96     fprintf (stderr, _("Try `%s --help\' for more information.\n"), get_identity ());
97     else
98     {
99     printf (_("Usage: %s [option]... NODENAME\n\n"), get_identity ());
100     printf (_
101     (" -c, --config=DIR Read configuration options from DIR.\n"
102     " -D, --no-detach Don't fork and detach.\n"
103     " -l, --log-level=LEVEL Set logging level (info, notice, warn are common).\n"
104 pcg 1.16 " -L, --mlock Lock gvpe into main memory.\n"
105 pcg 1.1 " --help Display this help and exit.\n"
106     " --version Output version information and exit.\n\n"));
107 pcg 1.9 printf (_("Report bugs to <gvpe@schmorp.de>.\n"));
108 pcg 1.1 }
109    
110     exit (status);
111     }
112    
113 root 1.18 static void
114 pcg 1.1 parse_options (int argc, char **argv, char **envp)
115     {
116     int r;
117     int option_index = 0;
118    
119 pcg 1.6 while ((r = getopt_long (argc, argv, "c:DLl:", long_options, &option_index)) != EOF)
120 pcg 1.1 {
121     switch (r)
122     {
123     case 0: /* long option */
124     break;
125    
126     case 'c': /* config file */
127     confbase = strdup (optarg);
128     break;
129    
130     case 'D': /* no detach */
131     do_detach = 0;
132     break;
133    
134     case 'L': /* lock into memory */
135     do_mlock = 1;
136     break;
137    
138     case 'l': /* inc debug level */
139     {
140     llevel = string_to_loglevel (optarg);
141    
142     if (llevel == L_NONE)
143     slog (L_WARN, "'%s': %s", optarg, UNKNOWN_LOGLEVEL);
144     }
145     break;
146    
147     case '?':
148     usage (1);
149    
150     default:
151     break;
152     }
153     }
154     }
155    
156 root 1.18 // close network connections, and terminate neatly
157     static void
158     cleanup_and_exit (int c)
159 pcg 1.1 {
160     network.shutdown_all ();
161    
162     if (conf.pidfilename)
163     remove_pid (conf.pidfilename);
164    
165     slog (L_INFO, _("terminating with exit code %d"), c);
166    
167     exit (c);
168     }
169    
170 root 1.18 // signal handlers
171     static RETSIGTYPE
172 pcg 1.1 sigterm_handler (int a)
173     {
174     network.events |= vpn::EVENT_SHUTDOWN;
175 pcg 1.10 network.event.start ();
176 pcg 1.1 }
177    
178 root 1.18 static RETSIGTYPE
179 pcg 1.1 sighup_handler (int a)
180     {
181     network.events |= vpn::EVENT_RECONNECT;
182 pcg 1.10 network.event.start ();
183 pcg 1.1 }
184    
185 root 1.18 static RETSIGTYPE
186 pcg 1.1 sigusr1_handler (int a)
187     {
188     network.dump_status ();
189     }
190    
191 root 1.18 static RETSIGTYPE
192 pcg 1.1 sigusr2_handler (int a)
193     {
194     }
195    
196 root 1.18 static void
197 pcg 1.1 setup_signals (void)
198     {
199     struct sigaction act;
200    
201     sigfillset (&act.sa_mask);
202     act.sa_flags = 0;
203    
204     act.sa_handler = sighup_handler; sigaction (SIGHUP , &act, NULL);
205     act.sa_handler = sigusr1_handler; sigaction (SIGUSR1, &act, NULL);
206     act.sa_handler = sigusr2_handler; sigaction (SIGUSR2, &act, NULL);
207     act.sa_handler = SIG_IGN; sigaction (SIGPIPE, &act, NULL);
208     act.sa_flags = SA_RESETHAND;
209     act.sa_handler = sigterm_handler; sigaction (SIGINT , &act, NULL);
210     act.sa_handler = sigterm_handler; sigaction (SIGTERM, &act, NULL);
211     }
212    
213 root 1.24 static int rand_fd;
214    
215     // antique C++ requires external linkage :/
216     void
217     reseed_rng (ev::timer &w, int revents)
218     {
219     char buf [SEED_SIZE];
220     int n = read (rand_fd, buf, sizeof (buf));
221    
222     if (n > 0)
223     RAND_seed (buf, n);
224     }
225    
226     static void
227     setup_rng (void)
228     {
229     if (!*conf.seed_dev)
230     return;
231    
232     #ifndef O_BINARY
233     # define O_BINARY 0
234     #endif
235     #ifndef O_NONBLOCK
236     # define O_NONBLOCK 0
237     #endif
238    
239     rand_fd = open (conf.seed_dev, O_RDONLY | O_NONBLOCK | O_BINARY);
240    
241     if (rand_fd < 0)
242     {
243     slog (L_ERR, _("unable to open seed device '%s': %s, exiting."), conf.seed_dev, strerror (errno));
244     exit (EXIT_FAILURE);
245     }
246    
247     static ev::timer reseed_timer;
248    
249     if (conf.reseed)
250     {
251     reseed_timer.set<reseed_rng> ();
252     reseed_timer.set (conf.reseed, conf.reseed);
253     reseed_timer.start (EV_DEFAULT);
254     }
255    
256     reseed_rng (reseed_timer, 0);
257     }
258    
259 pcg 1.1 int
260     main (int argc, char **argv, char **envp)
261     {
262     ERR_load_crypto_strings (); // we have the RAM
263    
264 root 1.25 require (EVP_MD_size (MAC_DIGEST ()) == HASH_SIZE (MAC_DIGEST ));
265     require (EVP_MD_size (AUTH_DIGEST ()) == HASH_SIZE (AUTH_DIGEST));
266     require (EVP_CIPHER_key_length (CIPHER ()) == KEY_SIZE (CIPHER ));
267     require (EVP_CIPHER_block_size (CIPHER ()) == BLOCK_SIZE (CIPHER ));
268    
269     curve25519_verify ();
270     hkdf::verify ();
271    
272 pcg 1.1 set_loglevel (L_INFO);
273     set_identity (argv[0]);
274     log_to (LOGTO_SYSLOG | LOGTO_STDERR);
275    
276     setlocale (LC_ALL, "");
277     bindtextdomain (PACKAGE, LOCALEDIR);
278     textdomain (PACKAGE);
279    
280     parse_options (argc, argv, envp);
281    
282 pcg 1.6 argc -= optind;
283     argv += optind;
284    
285 pcg 1.1 if (show_version)
286     {
287 pcg 1.9 printf (_("%s version %s (built %s %s, protocol version %d.%d)\n"), get_identity (),
288 pcg 1.1 VERSION, __DATE__, __TIME__, PROTOCOL_MAJOR, PROTOCOL_MINOR);
289     printf (_("Built with kernel interface %s/%s.\n"), IFTYPE, IFSUBTYPE);
290     printf (_
291 root 1.23 ("Copyright (C) 2003-2011 Marc Lehmann <gvpe@schmorp.de> and others.\n"
292 pcg 1.1 "See the AUTHORS file for a complete list.\n\n"
293 pcg 1.16 "GVPE comes with ABSOLUTELY NO WARRANTY. This is free software,\n"
294 pcg 1.1 "and you are welcome to redistribute it under certain conditions;\n"
295     "see the file COPYING for details.\n"));
296    
297     return 0;
298     }
299    
300     if (show_help)
301     usage (0);
302    
303     log_to (LOGTO_SYSLOG | LOGTO_STDERR);
304    
305     /* Lock all pages into memory if requested */
306    
307     #if HAVE_MLOCKALL && HAVE_SYS_MMAN_H && _POSIX_MEMLOCK
308     if (do_mlock)
309     if (mlockall (MCL_CURRENT | MCL_FUTURE))
310     slog (L_ERR, _("system call `%s' failed: %s"), "mlockall", strerror (errno));
311     #endif
312    
313 pcg 1.6 if (argc >= 1)
314     {
315     thisnode = *argv++;
316     argc--;
317     }
318    
319 pcg 1.12 if (!ev_default_loop (0))
320 pcg 1.10 {
321     slog (L_ERR, _("unable to initialise the event loop (bad $LIBEV_METHODS?)"));
322     exit (EXIT_FAILURE);
323     }
324    
325 pcg 1.6 {
326     configuration_parser (conf, true, argc, argv);
327     }
328 pcg 1.1
329     set_loglevel (llevel != L_NONE ? llevel : conf.llevel);
330    
331 root 1.24 setup_rng ();
332 pcg 1.1
333     if (!THISNODE)
334     {
335 pcg 1.3 slog (L_ERR, _("current node not set, or node '%s' not found in configfile, specify the nodename when starting gvpe."),
336 pcg 1.1 thisnode ? thisnode : "<unset>");
337     exit (EXIT_FAILURE);
338     }
339    
340     if (detach (do_detach))
341     exit (EXIT_SUCCESS);
342    
343     setup_signals ();
344    
345     if (!network.setup ())
346 root 1.22 if (network.drop_privileges ())
347     {
348     ev_run (EV_DEFAULT_ 0);
349     cleanup_and_exit (EXIT_FAILURE);
350     }
351 pcg 1.1
352 root 1.22 slog (L_CRIT, _("unrecoverable error while setting up network, exiting."));
353 pcg 1.1 cleanup_and_exit (EXIT_FAILURE);
354     }
355