ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/gvpe.C
Revision: 1.26
Committed: Thu Jan 29 00:21:39 2015 UTC (9 years, 3 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-3_0
Changes since 1.25: +3 -0 lines
Log Message:
*** empty log message ***

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.26 // m,ake sure openssl agrees with us on the important bits
265 root 1.25 require (EVP_MD_size (MAC_DIGEST ()) == HASH_SIZE (MAC_DIGEST ));
266     require (EVP_MD_size (AUTH_DIGEST ()) == HASH_SIZE (AUTH_DIGEST));
267     require (EVP_CIPHER_key_length (CIPHER ()) == KEY_SIZE (CIPHER ));
268     require (EVP_CIPHER_block_size (CIPHER ()) == BLOCK_SIZE (CIPHER ));
269 root 1.26 require (EVP_CIPHER_iv_length (CIPHER ()) == IV_SIZE (CIPHER ));
270     require (EVP_CIPHER_mode (CIPHER ()) == EVP_CIPH_CTR_MODE);
271 root 1.25
272     curve25519_verify ();
273     hkdf::verify ();
274    
275 pcg 1.1 set_loglevel (L_INFO);
276     set_identity (argv[0]);
277     log_to (LOGTO_SYSLOG | LOGTO_STDERR);
278    
279     setlocale (LC_ALL, "");
280     bindtextdomain (PACKAGE, LOCALEDIR);
281     textdomain (PACKAGE);
282    
283     parse_options (argc, argv, envp);
284    
285 pcg 1.6 argc -= optind;
286     argv += optind;
287    
288 pcg 1.1 if (show_version)
289     {
290 pcg 1.9 printf (_("%s version %s (built %s %s, protocol version %d.%d)\n"), get_identity (),
291 pcg 1.1 VERSION, __DATE__, __TIME__, PROTOCOL_MAJOR, PROTOCOL_MINOR);
292     printf (_("Built with kernel interface %s/%s.\n"), IFTYPE, IFSUBTYPE);
293     printf (_
294 root 1.23 ("Copyright (C) 2003-2011 Marc Lehmann <gvpe@schmorp.de> and others.\n"
295 pcg 1.1 "See the AUTHORS file for a complete list.\n\n"
296 pcg 1.16 "GVPE comes with ABSOLUTELY NO WARRANTY. This is free software,\n"
297 pcg 1.1 "and you are welcome to redistribute it under certain conditions;\n"
298     "see the file COPYING for details.\n"));
299    
300     return 0;
301     }
302    
303     if (show_help)
304     usage (0);
305    
306     log_to (LOGTO_SYSLOG | LOGTO_STDERR);
307    
308     /* Lock all pages into memory if requested */
309    
310     #if HAVE_MLOCKALL && HAVE_SYS_MMAN_H && _POSIX_MEMLOCK
311     if (do_mlock)
312     if (mlockall (MCL_CURRENT | MCL_FUTURE))
313     slog (L_ERR, _("system call `%s' failed: %s"), "mlockall", strerror (errno));
314     #endif
315    
316 pcg 1.6 if (argc >= 1)
317     {
318     thisnode = *argv++;
319     argc--;
320     }
321    
322 pcg 1.12 if (!ev_default_loop (0))
323 pcg 1.10 {
324     slog (L_ERR, _("unable to initialise the event loop (bad $LIBEV_METHODS?)"));
325     exit (EXIT_FAILURE);
326     }
327    
328 pcg 1.6 {
329     configuration_parser (conf, true, argc, argv);
330     }
331 pcg 1.1
332     set_loglevel (llevel != L_NONE ? llevel : conf.llevel);
333    
334 root 1.24 setup_rng ();
335 pcg 1.1
336     if (!THISNODE)
337     {
338 pcg 1.3 slog (L_ERR, _("current node not set, or node '%s' not found in configfile, specify the nodename when starting gvpe."),
339 pcg 1.1 thisnode ? thisnode : "<unset>");
340     exit (EXIT_FAILURE);
341     }
342    
343     if (detach (do_detach))
344     exit (EXIT_SUCCESS);
345    
346     setup_signals ();
347    
348     if (!network.setup ())
349 root 1.22 if (network.drop_privileges ())
350     {
351     ev_run (EV_DEFAULT_ 0);
352     cleanup_and_exit (EXIT_FAILURE);
353     }
354 pcg 1.1
355 root 1.22 slog (L_CRIT, _("unrecoverable error while setting up network, exiting."));
356 pcg 1.1 cleanup_and_exit (EXIT_FAILURE);
357     }
358