/* called after daemonization to retain signal settings */ void restore_signal_state(void) { #ifdef HAVE_SIGNAL_H if (signal_mode == SM_PRE_INIT) { pre_init_signal_catch(); } else if (signal_mode == SM_POST_INIT) { post_init_signal_catch(); } #endif }
/** * OpenVPN's main init-run-cleanup loop. * @ingroup eventloop * * This function contains the two outer OpenVPN loops. Its structure is * as follows: * - Once-per-process initialization. * - Outer loop, run at startup and then once per \c SIGHUP: * - Level 1 initialization * - Inner loop, run at startup and then once per \c SIGUSR1: * - Call event loop function depending on client or server mode: * - \c tunnel_point_to_point() * - \c tunnel_server() * - Level 1 cleanup * - Once-per-process cleanup. * * @param argc - Commandline argument count. * @param argv - Commandline argument values. */ 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 { /* enter pre-initialization mode with regard to signal handling */ pre_init_signal_catch (); /* 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 (NULL); #ifdef WIN32 env_set_add_win32 (c.es); #endif #ifdef ENABLE_MANAGEMENT /* initialize management subsystem */ init_management (&c); #endif /* initialize options to default state */ init_options (&c.options, true); /* parse command line options, and read configuration file */ parse_argv (&c.options, argc, argv, M_USAGE, OPT_P_DEFAULT, NULL, c.es); #ifdef ENABLE_PLUGIN /* plugins may contribute options configuration */ init_verb_mute (&c, IVM_LEVEL_1); init_plugins (&c); open_plugins (&c, true, OPENVPN_PLUGIN_INIT_PRE_CONFIG_PARSE); #endif /* 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); /* 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); env_set_destroy (c.es); #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 */ }