-int
-main(int argc, char **argv, char **envp)
-{
- program_name = argv[0];
-
- setlocale (LC_ALL, "");
- bindtextdomain (PACKAGE, LOCALEDIR);
- textdomain (PACKAGE);
-
- environment = envp;
- parse_options(argc, argv, envp);
-
- if(show_version)
- {
- printf(_("%s version %s (built %s %s, protocol %d)\n"), PACKAGE, VERSION, __DATE__, __TIME__, PROT_CURRENT);
- printf(_("Copyright (C) 1998-2001 Ivo Timmermans, Guus Sliepen and others.\n"
- "See the AUTHORS file for a complete list.\n\n"
- "tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\n"
- "and you are welcome to redistribute it under certain conditions;\n"
- "see the file COPYING for details.\n"));
-
- return 0;
- }
-
- if(show_help)
- usage(0);
-
- if(geteuid())
- {
- fprintf(stderr, _("You must be root to run this program.\n"));
- return 1;
- }
-
-#ifdef HAVE_SOLARIS
- openlog("tinc", LOG_CONS, LOG_DAEMON); /* Catch all syslog() calls issued before detaching */
-#else
- openlog("tinc", LOG_PERROR, LOG_DAEMON); /* Catch all syslog() calls issued before detaching */
-#endif
-
- g_argv = argv;
-
- make_names();
-
- /* Slllluuuuuuurrrrp! */
-cp
- RAND_load_file("/dev/urandom", 1024);
-cp
- if(generate_keys)
- {
- read_server_config();
- exit(keygen(generate_keys));
- }
-
- if(kill_tincd)
- exit(kill_other());
-
- if(read_server_config())
- exit(1);
-cp
- if(detach())
- exit(0);
-cp
- for(;;)
- {
- if(!setup_network_connections())
- {
- main_loop();
- cleanup_and_exit(1);
- }
-
- syslog(LOG_ERR, _("Unrecoverable error"));
- cp_trace();
-
- if(do_detach)
- {
- syslog(LOG_NOTICE, _("Restarting in %d seconds!"), MAXTIMEOUT);
- sleep(MAXTIMEOUT);
- }
- else
- {
- syslog(LOG_ERR, _("Not restarting."));
- exit(1);
- }
- }
+int main(int argc, char **argv) {
+ program_name = argv[0];
+
+ if(!parse_options(argc, argv)) {
+ return 1;
+ }
+
+ if(show_version) {
+ printf("%s version %s (built %s %s, protocol %d.%d)\n", PACKAGE,
+ BUILD_VERSION, BUILD_DATE, BUILD_TIME, PROT_MAJOR, PROT_MINOR);
+ printf("Features:"
+#ifdef HAVE_OPENSSL
+ " openssl"
+#endif
+#ifdef HAVE_LIBGCRYPT
+ " libgcrypt"
+#endif
+#ifdef HAVE_LZO
+ " comp_lzo"
+#endif
+#ifdef HAVE_ZLIB
+ " comp_zlib"
+#endif
+#ifdef HAVE_LZ4
+ " comp_lz4"
+#endif
+#ifndef DISABLE_LEGACY
+ " legacy_protocol"
+#endif
+#ifdef ENABLE_JUMBOGRAMS
+ " jumbograms"
+#endif
+#ifdef ENABLE_TUNEMU
+ " tunemu"
+#endif
+#ifdef HAVE_MINIUPNPC
+ " miniupnpc"
+#endif
+#ifdef ENABLE_UML
+ " uml"
+#endif
+#ifdef ENABLE_VDE
+ " vde"
+#endif
+ "\n\n");
+ printf("Copyright (C) 1998-2021 Ivo Timmermans, Guus Sliepen and others.\n"
+ "See the AUTHORS file for a complete list.\n\n"
+ "tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\n"
+ "and you are welcome to redistribute it under certain conditions;\n"
+ "see the file COPYING for details.\n");
+
+ return 0;
+ }
+
+ if(show_help) {
+ usage(false);
+ return 0;
+ }
+
+ make_names(true);
+ atexit(cleanup);
+
+ chdir(confbase);
+
+#ifdef HAVE_MINGW
+
+ if(WSAStartup(MAKEWORD(2, 2), &wsa_state)) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "WSAStartup", winerror(GetLastError()));
+ return 1;
+ }
+
+#else
+ // Check if we got an umbilical fd from the process that started us
+ char *umbstr = getenv("TINC_UMBILICAL");
+
+ if(umbstr) {
+ umbilical = atoi(umbstr);
+
+ if(fcntl(umbilical, F_GETFL) < 0) {
+ umbilical = 0;
+ }
+
+#ifdef FD_CLOEXEC
+
+ if(umbilical) {
+ fcntl(umbilical, F_SETFD, FD_CLOEXEC);
+ }
+
+#endif
+ }
+
+#endif
+
+ openlogger("tinc", use_logfile ? LOGMODE_FILE : LOGMODE_STDERR);
+
+ g_argv = argv;
+
+ if(getenv("LISTEN_PID") && atoi(getenv("LISTEN_PID")) == getpid()) {
+ do_detach = false;
+ }
+
+#ifdef HAVE_UNSETENV
+ unsetenv("LISTEN_PID");
+#endif
+
+ /* Slllluuuuuuurrrrp! */
+
+ crypto_init();
+
+ if(!read_server_config(&config_tree)) {
+ return 1;
+ }
+
+ if(debug_level == DEBUG_NOTHING) {
+ int level = 0;
+
+ if(get_config_int(lookup_config(&config_tree, "LogLevel"), &level)) {
+ debug_level = level;
+ }
+ }
+
+#ifdef HAVE_LZO
+
+ if(lzo_init() != LZO_E_OK) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "Error initializing LZO compressor!");
+ return 1;
+ }
+
+#endif
+
+#ifdef HAVE_MINGW
+ io_add_event(&stop_io, stop_handler, NULL, WSACreateEvent());
+
+ if(stop_io.event == FALSE) {
+ abort();
+ }
+
+ int result;
+
+ if(!do_detach || !init_service()) {
+ SetConsoleCtrlHandler(console_ctrl_handler, TRUE);
+ result = main2(argc, argv);
+ } else {
+ result = 1;
+ }
+
+ if(WSACloseEvent(stop_io.event) == FALSE) {
+ abort();
+ }
+
+ io_del(&stop_io);
+ return result;
+}
+
+int main2(int argc, char **argv) {
+ (void)argc;
+ (void)argv;
+#endif
+ char *priority = NULL;
+
+ gettimeofday(&now, NULL);
+ srand(now.tv_sec + now.tv_usec);
+
+ if(!detach()) {
+ return 1;
+ }
+
+#ifdef HAVE_MLOCKALL
+
+ /* Lock all pages into memory if requested.
+ * This has to be done after daemon()/fork() so it works for child.
+ * No need to do that in parent as it's very short-lived. */
+ if(do_mlock && mlockall(MCL_CURRENT | MCL_FUTURE) != 0) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "mlockall",
+ strerror(errno));
+ return 1;
+ }
+
+#endif
+
+ /* Setup sockets and open device. */
+
+ if(!setup_network()) {
+ goto end;
+ }
+
+ /* Change process priority */
+
+ if(get_config_string(lookup_config(&config_tree, "ProcessPriority"), &priority)) {
+ if(!strcasecmp(priority, "Normal")) {
+ if(setpriority(NORMAL_PRIORITY_CLASS) != 0) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "setpriority", strerror(errno));
+ goto end;
+ }
+ } else if(!strcasecmp(priority, "Low")) {
+ if(setpriority(BELOW_NORMAL_PRIORITY_CLASS) != 0) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "setpriority", strerror(errno));
+ goto end;
+ }
+ } else if(!strcasecmp(priority, "High")) {
+ if(setpriority(HIGH_PRIORITY_CLASS) != 0) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "setpriority", strerror(errno));
+ goto end;
+ }
+ } else {
+ logger(DEBUG_ALWAYS, LOG_ERR, "Invalid priority `%s`!", priority);
+ goto end;
+ }
+ }
+
+ /* drop privileges */
+ if(!drop_privs()) {
+ goto end;
+ }
+
+ /* Start main loop. It only exits when tinc is killed. */
+
+ logger(DEBUG_ALWAYS, LOG_NOTICE, "Ready");
+
+ if(umbilical) { // snip!
+ write(umbilical, "", 1);
+ close(umbilical);
+ umbilical = 0;
+ }
+
+ try_outgoing_connections();
+
+ status = main_loop();
+
+ /* Shutdown properly. */
+
+end:
+ close_network_connections();
+
+ logger(DEBUG_ALWAYS, LOG_NOTICE, "Terminating");
+
+ free(priority);
+
+ crypto_exit();
+
+ return status;