ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/gvpe.C
Revision: 1.27
Committed: Thu Oct 6 03:25:54 2022 UTC (19 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.26: +4 -4 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 #include "hkdf.h"
66
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 {
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
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 " -L, --mlock Lock gvpe into main memory.\n"
105 " --help Display this help and exit.\n"
106 " --version Output version information and exit.\n\n"));
107 printf (_("Report bugs to <gvpe@schmorp.de>.\n"));
108 }
109
110 exit (status);
111 }
112
113 static void
114 parse_options (int argc, char **argv, char **envp)
115 {
116 int r;
117 int option_index = 0;
118
119 while ((r = getopt_long (argc, argv, "c:DLl:", long_options, &option_index)) != EOF)
120 {
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 // close network connections, and terminate neatly
157 static void
158 cleanup_and_exit (int c)
159 {
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 // signal handlers
171 static void
172 sigterm_handler (int a)
173 {
174 network.events |= vpn::EVENT_SHUTDOWN;
175 network.event.start ();
176 }
177
178 static void
179 sighup_handler (int a)
180 {
181 network.events |= vpn::EVENT_RECONNECT;
182 network.event.start ();
183 }
184
185 static void
186 sigusr1_handler (int a)
187 {
188 network.dump_status ();
189 }
190
191 static void
192 sigusr2_handler (int a)
193 {
194 }
195
196 static void
197 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 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 int
260 main (int argc, char **argv, char **envp)
261 {
262 ERR_load_crypto_strings (); // we have the RAM
263
264 // m,ake sure openssl agrees with us on the important bits
265 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 require (EVP_CIPHER_iv_length (CIPHER ()) == IV_SIZE (CIPHER ));
270 require (EVP_CIPHER_mode (CIPHER ()) == EVP_CIPH_CTR_MODE);
271
272 curve25519_verify ();
273 hkdf::verify ();
274
275 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 argc -= optind;
286 argv += optind;
287
288 if (show_version)
289 {
290 printf (_("%s version %s (built %s %s, protocol version %d.%d)\n"), get_identity (),
291 VERSION, __DATE__, __TIME__, PROTOCOL_MAJOR, PROTOCOL_MINOR);
292 printf (_("Built with kernel interface %s/%s.\n"), IFTYPE, IFSUBTYPE);
293 printf (_
294 ("Copyright (C) 2003-2011 Marc Lehmann <gvpe@schmorp.de> and others.\n"
295 "See the AUTHORS file for a complete list.\n\n"
296 "GVPE comes with ABSOLUTELY NO WARRANTY. This is free software,\n"
297 "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 if (argc >= 1)
317 {
318 thisnode = *argv++;
319 argc--;
320 }
321
322 if (!ev_default_loop (0))
323 {
324 slog (L_ERR, _("unable to initialise the event loop (bad $LIBEV_METHODS?)"));
325 exit (EXIT_FAILURE);
326 }
327
328 {
329 configuration_parser (conf, true, argc, argv);
330 }
331
332 set_loglevel (llevel != L_NONE ? llevel : conf.llevel);
333
334 setup_rng ();
335
336 if (!THISNODE)
337 {
338 slog (L_ERR, _("current node not set, or node '%s' not found in configfile, specify the nodename when starting gvpe."),
339 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 if (network.drop_privileges ())
350 {
351 ev_run (EV_DEFAULT_ 0);
352 cleanup_and_exit (EXIT_FAILURE);
353 }
354
355 slog (L_CRIT, _("unrecoverable error while setting up network, exiting."));
356 cleanup_and_exit (EXIT_FAILURE);
357 }
358