aboutsummaryrefslogtreecommitdiff
path: root/openvpn.c
diff options
context:
space:
mode:
Diffstat (limited to 'openvpn.c')
-rw-r--r--openvpn.c242
1 files changed, 242 insertions, 0 deletions
diff --git a/openvpn.c b/openvpn.c
new file mode 100644
index 0000000..47701f9
--- /dev/null
+++ b/openvpn.c
@@ -0,0 +1,242 @@
+/*
+ * OpenVPN -- An application to securely tunnel IP networks
+ * over a single TCP/UDP port, with support for SSL/TLS-based
+ * session authentication and key exchange,
+ * packet encryption, packet authentication, and
+ * packet compression.
+ *
+ * Copyright (C) 2002-2005 OpenVPN Solutions LLC <info@openvpn.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (see the file COPYING included with this
+ * distribution); if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifdef WIN32
+#include "config-win32.h"
+#else
+#include "config.h"
+#endif
+
+#include "syshead.h"
+
+#include "init.h"
+#include "forward.h"
+#include "multi.h"
+
+#include "memdbg.h"
+
+#include "forward-inline.h"
+
+#define P2P_CHECK_SIG() EVENT_LOOP_CHECK_SIGNAL (c, process_signal_p2p, c);
+
+static bool
+process_signal_p2p (struct context *c)
+{
+ remap_signal (c);
+ return process_signal (c);
+}
+
+static void
+tunnel_point_to_point (struct context *c)
+{
+ context_clear_2 (c);
+
+ /* set point-to-point mode */
+ c->mode = CM_P2P;
+
+ /* initialize tunnel instance */
+ init_instance_handle_signals (c, c->es, CC_HARD_USR1_TO_HUP);
+ if (IS_SIG (c))
+ return;
+
+ init_management_callback_p2p (c);
+
+ /* main event loop */
+ while (true)
+ {
+ perf_push (PERF_EVENT_LOOP);
+
+ /* process timers, TLS, etc. */
+ pre_select (c);
+ P2P_CHECK_SIG();
+
+ /* set up and do the I/O wait */
+ io_wait (c, p2p_iow_flags (c));
+ P2P_CHECK_SIG();
+
+ /* timeout? */
+ if (c->c2.event_set_status == ES_TIMEOUT)
+ {
+ perf_pop ();
+ continue;
+ }
+
+ /* process the I/O which triggered select */
+ process_io (c);
+ P2P_CHECK_SIG();
+
+ perf_pop ();
+ }
+
+ uninit_management_callback ();
+
+ /* tear down tunnel instance (unless --persist-tun) */
+ close_instance (c);
+}
+
+#undef PROCESS_SIGNAL_P2P
+
+int
+main (int argc, char *argv[])
+{
+ struct context c;
+
+#if PEDANTIC
+ fprintf (stderr, "Sorry, I was built with --enable-pedantic and I am incapable of doing any real work!\n");
+ return 1;
+#endif
+
+ CLEAR (c);
+
+ /* signify first time for components which can
+ only be initialized once per program instantiation. */
+ c.first_time = true;
+
+ /* initialize program-wide statics */
+ if (init_static ())
+ {
+ /*
+ * This loop is initially executed on startup and then
+ * once per SIGHUP.
+ */
+ do
+ {
+ /* zero context struct but leave first_time member alone */
+ context_clear_all_except_first_time (&c);
+
+ /* static signal info object */
+ CLEAR (siginfo_static);
+ c.sig = &siginfo_static;
+
+ /* initialize garbage collector scoped to context object */
+ gc_init (&c.gc);
+
+ /* initialize environmental variable store */
+ c.es = env_set_create (&c.gc);
+
+#ifdef ENABLE_MANAGEMENT
+ /* initialize management subsystem */
+ init_management (&c);
+#endif
+
+ /* initialize options to default state */
+ init_options (&c.options);
+
+ /* parse command line options, and read configuration file */
+ parse_argv (&c.options, argc, argv, M_USAGE, OPT_P_DEFAULT, NULL, c.es);
+
+ /* init verbosity and mute levels */
+ init_verb_mute (&c, IVM_LEVEL_1);
+
+ /* set dev options */
+ init_options_dev (&c.options);
+
+ /* openssl print info? */
+ if (print_openssl_info (&c.options))
+ break;
+
+ /* --genkey mode? */
+ if (do_genkey (&c.options))
+ break;
+
+ /* tun/tap persist command? */
+ if (do_persist_tuntap (&c.options))
+ break;
+
+ /* sanity check on options */
+ options_postprocess (&c.options, c.first_time);
+
+ /* show all option settings */
+ show_settings (&c.options);
+
+ /* print version number */
+ msg (M_INFO, "%s", title_string);
+
+ /* misc stuff */
+ pre_setup (&c.options);
+
+ /* test crypto? */
+ if (do_test_crypto (&c.options))
+ break;
+
+#ifdef ENABLE_MANAGEMENT
+ /* open management subsystem */
+ if (!open_management (&c))
+ break;
+#endif
+
+ /* set certain options as environmental variables */
+ setenv_settings (c.es, &c.options);
+
+ /* finish context init */
+ context_init_1 (&c);
+
+ do
+ {
+ /* run tunnel depending on mode */
+ switch (c.options.mode)
+ {
+ case MODE_POINT_TO_POINT:
+ tunnel_point_to_point (&c);
+ break;
+#if P2MP_SERVER
+ case MODE_SERVER:
+ tunnel_server (&c);
+ break;
+#endif
+ default:
+ ASSERT (0);
+ }
+
+ /* indicates first iteration -- has program-wide scope */
+ c.first_time = false;
+
+ /* any signals received? */
+ if (IS_SIG (&c))
+ print_signal (c.sig, NULL, M_INFO);
+
+ /* pass restart status to management subsystem */
+ signal_restart_status (c.sig);
+ }
+ while (c.sig->signal_received == SIGUSR1);
+
+ uninit_options (&c.options);
+ gc_reset (&c.gc);
+ }
+ while (c.sig->signal_received == SIGHUP);
+ }
+
+ context_gc_free (&c);
+
+#ifdef ENABLE_MANAGEMENT
+ /* close management interface */
+ close_management ();
+#endif
+
+ /* uninitialize program-wide statics */
+ uninit_static ();
+
+ openvpn_exit (OPENVPN_EXIT_STATUS_GOOD); /* exit point */
+ return 0; /* NOTREACHED */
+}