tor_api.c (4299B)
1 /* Copyright (c) 2001 Matej Pfajfar. 2 * Copyright (c) 2001-2004, Roger Dingledine. 3 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. 4 * Copyright (c) 2007-2021, The Tor Project, Inc. */ 5 /* See LICENSE for licensing information */ 6 7 /** 8 * \file tor_api.c 9 **/ 10 11 #ifdef _WIN32 12 #include <winsock2.h> 13 #include <windows.h> 14 #endif 15 16 #include "feature/api/tor_api.h" 17 18 // Include this after the above headers, to insure that they don't 19 // depend on anything else. 20 #include "orconfig.h" 21 #include "lib/cc/compat_compiler.h" 22 #include "lib/cc/torint.h" 23 #include "feature/api/tor_api_internal.h" 24 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <string.h> 28 29 // We don't want to use tor_malloc and tor_free here, since this needs 30 // to run before anything is initialized at all, and ought to run when 31 // we're not linked to anything at all. 32 33 #define raw_malloc malloc 34 #define raw_free free 35 #define raw_realloc realloc 36 #define raw_strdup strdup 37 38 #ifdef _WIN32 39 #include "lib/net/socketpair.h" 40 #define raw_socketpair tor_ersatz_socketpair 41 #define raw_closesocket closesocket 42 #if !defined(HAVE_SNPRINTF) 43 #define snprintf _snprintf 44 #endif 45 #else /* !defined(_WIN32) */ 46 #define raw_socketpair socketpair 47 #define raw_closesocket close 48 #endif /* defined(_WIN32) */ 49 50 #ifdef HAVE_UNISTD_H 51 #include <unistd.h> 52 #endif 53 54 /** 55 * Helper: Add a copy of <b>arg</b> to the owned arguments of <b>cfg</b>. 56 * Return 0 on success, -1 on failure. 57 */ 58 static int 59 cfg_add_owned_arg(tor_main_configuration_t *cfg, const char *arg) 60 { 61 /* We aren't using amortized realloc here, because libc should do it for us, 62 * and because this function is not critical-path. */ 63 char **new_argv = raw_realloc(cfg->argv_owned, 64 sizeof(char*) * (cfg->argc_owned+1)); 65 if (new_argv == NULL) 66 return -1; 67 cfg->argv_owned = new_argv; 68 if (NULL == (cfg->argv_owned[cfg->argc_owned] = raw_strdup(arg))) 69 return -1; 70 ++cfg->argc_owned; 71 return 0; 72 } 73 74 tor_main_configuration_t * 75 tor_main_configuration_new(void) 76 { 77 static const char *fake_argv[] = { "tor" }; 78 tor_main_configuration_t *cfg = raw_malloc(sizeof(*cfg)); 79 if (cfg == NULL) 80 return NULL; 81 82 memset(cfg, 0, sizeof(*cfg)); 83 84 cfg->argc = 1; 85 cfg->argv = (char **) fake_argv; 86 87 cfg->owning_controller_socket = TOR_INVALID_SOCKET; 88 89 return cfg; 90 } 91 92 int 93 tor_main_configuration_set_command_line(tor_main_configuration_t *cfg, 94 int argc, char *argv[]) 95 { 96 if (cfg == NULL) 97 return -1; 98 cfg->argc = argc; 99 cfg->argv = argv; 100 return 0; 101 } 102 103 tor_control_socket_t 104 tor_main_configuration_setup_control_socket(tor_main_configuration_t *cfg) 105 { 106 if (SOCKET_OK(cfg->owning_controller_socket)) 107 return INVALID_TOR_CONTROL_SOCKET; 108 109 tor_socket_t fds[2]; 110 if (raw_socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { 111 return INVALID_TOR_CONTROL_SOCKET; 112 } 113 char buf[32]; 114 snprintf(buf, sizeof(buf), "%"PRIu64, (uint64_t)fds[1]); 115 116 cfg_add_owned_arg(cfg, "__OwningControllerFD"); 117 cfg_add_owned_arg(cfg, buf); 118 119 cfg->owning_controller_socket = fds[1]; 120 return fds[0]; 121 } 122 123 void 124 tor_main_configuration_free(tor_main_configuration_t *cfg) 125 { 126 if (cfg == NULL) 127 return; 128 if (cfg->argv_owned) { 129 for (int i = 0; i < cfg->argc_owned; ++i) { 130 raw_free(cfg->argv_owned[i]); 131 } 132 raw_free(cfg->argv_owned); 133 } 134 if (SOCKET_OK(cfg->owning_controller_socket)) { 135 raw_closesocket(cfg->owning_controller_socket); 136 } 137 raw_free(cfg); 138 } 139 140 const char * 141 tor_api_get_provider_version(void) 142 { 143 return "tor " VERSION; 144 } 145 146 /* Main entry point for the Tor process. Called from main(). 147 * 148 * This function is distinct from main() only so we can link main.c into 149 * the unittest binary without conflicting with the unittests' main. 150 * 151 * Some embedders have historically called this function; but that usage is 152 * deprecated: they should use tor_run_main() instead. 153 */ 154 int 155 tor_main(int argc, char *argv[]) 156 { 157 tor_main_configuration_t *cfg = tor_main_configuration_new(); 158 if (!cfg) { 159 puts("INTERNAL ERROR: Allocation failure. Cannot proceed"); 160 return 1; 161 } 162 if (tor_main_configuration_set_command_line(cfg, argc, argv) < 0) { 163 puts("INTERNAL ERROR: Can't set command line. Cannot proceed."); 164 return 1; 165 } 166 int rv = tor_run_main(cfg); 167 tor_main_configuration_free(cfg); 168 return rv; 169 }