ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/gvpe.C
Revision: 1.24
Committed: Sat Jul 13 04:10:29 2013 UTC (10 years, 10 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_25
Changes since 1.23: +49 -2 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 pcg 1.1
66     static loglevel llevel = L_NONE;
67    
68     /* If nonzero, display usage information and exit. */
69     static int show_help;
70    
71     /* If nonzero, print the version on standard output and exit. */
72     static int show_version;
73    
74     /* If nonzero, disable swapping for this process. */
75     static int do_mlock = 0;
76    
77     /* If zero, don't detach from the terminal. */
78     static int do_detach = 1;
79    
80     static struct option const long_options[] =
81 root 1.18 {
82     {"config", required_argument, NULL, 'c'},
83     {"help", no_argument, &show_help, 1},
84     {"version", no_argument, &show_version, 1},
85     {"no-detach", no_argument, &do_detach, 0},
86     {"log-level", required_argument, NULL, 'l'},
87     {"mlock", no_argument, &do_mlock, 1},
88     {NULL, 0, NULL, 0}
89     };
90 pcg 1.1
91     static void
92     usage (int status)
93     {
94     if (status != 0)
95     fprintf (stderr, _("Try `%s --help\' for more information.\n"), get_identity ());
96     else
97     {
98     printf (_("Usage: %s [option]... NODENAME\n\n"), get_identity ());
99     printf (_
100     (" -c, --config=DIR Read configuration options from DIR.\n"
101     " -D, --no-detach Don't fork and detach.\n"
102     " -l, --log-level=LEVEL Set logging level (info, notice, warn are common).\n"
103 pcg 1.16 " -L, --mlock Lock gvpe into main memory.\n"
104 pcg 1.1 " --help Display this help and exit.\n"
105     " --version Output version information and exit.\n\n"));
106 pcg 1.9 printf (_("Report bugs to <gvpe@schmorp.de>.\n"));
107 pcg 1.1 }
108    
109     exit (status);
110     }
111    
112 root 1.18 static void
113 pcg 1.1 parse_options (int argc, char **argv, char **envp)
114     {
115     int r;
116     int option_index = 0;
117    
118 pcg 1.6 while ((r = getopt_long (argc, argv, "c:DLl:", long_options, &option_index)) != EOF)
119 pcg 1.1 {
120     switch (r)
121     {
122     case 0: /* long option */
123     break;
124    
125     case 'c': /* config file */
126     confbase = strdup (optarg);
127     break;
128    
129     case 'D': /* no detach */
130     do_detach = 0;
131     break;
132    
133     case 'L': /* lock into memory */
134     do_mlock = 1;
135     break;
136    
137     case 'l': /* inc debug level */
138     {
139     llevel = string_to_loglevel (optarg);
140    
141     if (llevel == L_NONE)
142     slog (L_WARN, "'%s': %s", optarg, UNKNOWN_LOGLEVEL);
143     }
144     break;
145    
146     case '?':
147     usage (1);
148    
149     default:
150     break;
151     }
152     }
153     }
154    
155 root 1.18 // close network connections, and terminate neatly
156     static void
157     cleanup_and_exit (int c)
158 pcg 1.1 {
159     network.shutdown_all ();
160    
161     if (conf.pidfilename)
162     remove_pid (conf.pidfilename);
163    
164     slog (L_INFO, _("terminating with exit code %d"), c);
165    
166     exit (c);
167     }
168    
169 root 1.18 // signal handlers
170     static RETSIGTYPE
171 pcg 1.1 sigterm_handler (int a)
172     {
173     network.events |= vpn::EVENT_SHUTDOWN;
174 pcg 1.10 network.event.start ();
175 pcg 1.1 }
176    
177 root 1.18 static RETSIGTYPE
178 pcg 1.1 sighup_handler (int a)
179     {
180     network.events |= vpn::EVENT_RECONNECT;
181 pcg 1.10 network.event.start ();
182 pcg 1.1 }
183    
184 root 1.18 static RETSIGTYPE
185 pcg 1.1 sigusr1_handler (int a)
186     {
187     network.dump_status ();
188     }
189    
190 root 1.18 static RETSIGTYPE
191 pcg 1.1 sigusr2_handler (int a)
192     {
193     }
194    
195 root 1.18 static void
196 pcg 1.1 setup_signals (void)
197     {
198     struct sigaction act;
199    
200     sigfillset (&act.sa_mask);
201     act.sa_flags = 0;
202    
203     act.sa_handler = sighup_handler; sigaction (SIGHUP , &act, NULL);
204     act.sa_handler = sigusr1_handler; sigaction (SIGUSR1, &act, NULL);
205     act.sa_handler = sigusr2_handler; sigaction (SIGUSR2, &act, NULL);
206     act.sa_handler = SIG_IGN; sigaction (SIGPIPE, &act, NULL);
207     act.sa_flags = SA_RESETHAND;
208     act.sa_handler = sigterm_handler; sigaction (SIGINT , &act, NULL);
209     act.sa_handler = sigterm_handler; sigaction (SIGTERM, &act, NULL);
210     }
211    
212 root 1.24 static int rand_fd;
213    
214     // antique C++ requires external linkage :/
215     void
216     reseed_rng (ev::timer &w, int revents)
217     {
218     char buf [SEED_SIZE];
219     int n = read (rand_fd, buf, sizeof (buf));
220    
221     if (n > 0)
222     RAND_seed (buf, n);
223     }
224    
225     static void
226     setup_rng (void)
227     {
228     if (!*conf.seed_dev)
229     return;
230    
231     #ifndef O_BINARY
232     # define O_BINARY 0
233     #endif
234     #ifndef O_NONBLOCK
235     # define O_NONBLOCK 0
236     #endif
237    
238     rand_fd = open (conf.seed_dev, O_RDONLY | O_NONBLOCK | O_BINARY);
239    
240     if (rand_fd < 0)
241     {
242     slog (L_ERR, _("unable to open seed device '%s': %s, exiting."), conf.seed_dev, strerror (errno));
243     exit (EXIT_FAILURE);
244     }
245    
246     static ev::timer reseed_timer;
247    
248     if (conf.reseed)
249     {
250     reseed_timer.set<reseed_rng> ();
251     reseed_timer.set (conf.reseed, conf.reseed);
252     reseed_timer.start (EV_DEFAULT);
253     }
254    
255     reseed_rng (reseed_timer, 0);
256     }
257    
258 pcg 1.1 int
259     main (int argc, char **argv, char **envp)
260     {
261     ERR_load_crypto_strings (); // we have the RAM
262    
263     set_loglevel (L_INFO);
264     set_identity (argv[0]);
265     log_to (LOGTO_SYSLOG | LOGTO_STDERR);
266    
267     setlocale (LC_ALL, "");
268     bindtextdomain (PACKAGE, LOCALEDIR);
269     textdomain (PACKAGE);
270    
271     parse_options (argc, argv, envp);
272    
273 pcg 1.6 argc -= optind;
274     argv += optind;
275    
276 pcg 1.1 if (show_version)
277     {
278 pcg 1.9 printf (_("%s version %s (built %s %s, protocol version %d.%d)\n"), get_identity (),
279 pcg 1.1 VERSION, __DATE__, __TIME__, PROTOCOL_MAJOR, PROTOCOL_MINOR);
280     printf (_("Built with kernel interface %s/%s.\n"), IFTYPE, IFSUBTYPE);
281     printf (_
282 root 1.23 ("Copyright (C) 2003-2011 Marc Lehmann <gvpe@schmorp.de> and others.\n"
283 pcg 1.1 "See the AUTHORS file for a complete list.\n\n"
284 pcg 1.16 "GVPE comes with ABSOLUTELY NO WARRANTY. This is free software,\n"
285 pcg 1.1 "and you are welcome to redistribute it under certain conditions;\n"
286     "see the file COPYING for details.\n"));
287    
288     return 0;
289     }
290    
291     if (show_help)
292     usage (0);
293    
294     log_to (LOGTO_SYSLOG | LOGTO_STDERR);
295    
296     /* Lock all pages into memory if requested */
297    
298     #if HAVE_MLOCKALL && HAVE_SYS_MMAN_H && _POSIX_MEMLOCK
299     if (do_mlock)
300     if (mlockall (MCL_CURRENT | MCL_FUTURE))
301     slog (L_ERR, _("system call `%s' failed: %s"), "mlockall", strerror (errno));
302     #endif
303    
304 pcg 1.6 if (argc >= 1)
305     {
306     thisnode = *argv++;
307     argc--;
308     }
309    
310 pcg 1.12 if (!ev_default_loop (0))
311 pcg 1.10 {
312     slog (L_ERR, _("unable to initialise the event loop (bad $LIBEV_METHODS?)"));
313     exit (EXIT_FAILURE);
314     }
315    
316 pcg 1.6 {
317     configuration_parser (conf, true, argc, argv);
318     }
319 pcg 1.1
320     set_loglevel (llevel != L_NONE ? llevel : conf.llevel);
321    
322 root 1.24 setup_rng ();
323 pcg 1.1
324     if (!THISNODE)
325     {
326 pcg 1.3 slog (L_ERR, _("current node not set, or node '%s' not found in configfile, specify the nodename when starting gvpe."),
327 pcg 1.1 thisnode ? thisnode : "<unset>");
328     exit (EXIT_FAILURE);
329     }
330    
331     if (detach (do_detach))
332     exit (EXIT_SUCCESS);
333    
334     setup_signals ();
335    
336     if (!network.setup ())
337 root 1.22 if (network.drop_privileges ())
338     {
339     ev_run (EV_DEFAULT_ 0);
340     cleanup_and_exit (EXIT_FAILURE);
341     }
342 pcg 1.1
343 root 1.22 slog (L_CRIT, _("unrecoverable error while setting up network, exiting."));
344 pcg 1.1 cleanup_and_exit (EXIT_FAILURE);
345     }
346