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

# Content
1 /*
2 gvpe.C -- the main file for gvpe
3 Copyright (C) 1998-2002 Ivo Timmermans <ivo@o2w.nl>
4 2000-2002 Guus Sliepen <guus@sliepen.eu.org>
5 2003-2013 Marc Lehmann <gvpe@schmorp.de>
6
7 This file is part of GVPE.
8
9 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 */
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 #include <sys/stat.h>
46 #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 #include "gettext.h"
58 #include "pidfile.h"
59
60 #include "conf.h"
61 #include "slog.h"
62 #include "util.h"
63 #include "vpn.h"
64 #include "ev_cpp.h"
65
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 {
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
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 " -L, --mlock Lock gvpe into main memory.\n"
104 " --help Display this help and exit.\n"
105 " --version Output version information and exit.\n\n"));
106 printf (_("Report bugs to <gvpe@schmorp.de>.\n"));
107 }
108
109 exit (status);
110 }
111
112 static void
113 parse_options (int argc, char **argv, char **envp)
114 {
115 int r;
116 int option_index = 0;
117
118 while ((r = getopt_long (argc, argv, "c:DLl:", long_options, &option_index)) != EOF)
119 {
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 // close network connections, and terminate neatly
156 static void
157 cleanup_and_exit (int c)
158 {
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 // signal handlers
170 static RETSIGTYPE
171 sigterm_handler (int a)
172 {
173 network.events |= vpn::EVENT_SHUTDOWN;
174 network.event.start ();
175 }
176
177 static RETSIGTYPE
178 sighup_handler (int a)
179 {
180 network.events |= vpn::EVENT_RECONNECT;
181 network.event.start ();
182 }
183
184 static RETSIGTYPE
185 sigusr1_handler (int a)
186 {
187 network.dump_status ();
188 }
189
190 static RETSIGTYPE
191 sigusr2_handler (int a)
192 {
193 }
194
195 static void
196 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 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 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 argc -= optind;
274 argv += optind;
275
276 if (show_version)
277 {
278 printf (_("%s version %s (built %s %s, protocol version %d.%d)\n"), get_identity (),
279 VERSION, __DATE__, __TIME__, PROTOCOL_MAJOR, PROTOCOL_MINOR);
280 printf (_("Built with kernel interface %s/%s.\n"), IFTYPE, IFSUBTYPE);
281 printf (_
282 ("Copyright (C) 2003-2011 Marc Lehmann <gvpe@schmorp.de> and others.\n"
283 "See the AUTHORS file for a complete list.\n\n"
284 "GVPE comes with ABSOLUTELY NO WARRANTY. This is free software,\n"
285 "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 if (argc >= 1)
305 {
306 thisnode = *argv++;
307 argc--;
308 }
309
310 if (!ev_default_loop (0))
311 {
312 slog (L_ERR, _("unable to initialise the event loop (bad $LIBEV_METHODS?)"));
313 exit (EXIT_FAILURE);
314 }
315
316 {
317 configuration_parser (conf, true, argc, argv);
318 }
319
320 set_loglevel (llevel != L_NONE ? llevel : conf.llevel);
321
322 setup_rng ();
323
324 if (!THISNODE)
325 {
326 slog (L_ERR, _("current node not set, or node '%s' not found in configfile, specify the nodename when starting gvpe."),
327 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 if (network.drop_privileges ())
338 {
339 ev_run (EV_DEFAULT_ 0);
340 cleanup_and_exit (EXIT_FAILURE);
341 }
342
343 slog (L_CRIT, _("unrecoverable error while setting up network, exiting."));
344 cleanup_and_exit (EXIT_FAILURE);
345 }
346