int start_plugin(const char *plugin, const char *plugin_opts, const char *remote_host, const char *remote_port, const char *local_host, const char *local_port, #ifdef __MINGW32__ uint16_t control_port, #endif enum plugin_mode mode) { #ifndef __MINGW32__ char *new_path = NULL; const char *current_path; size_t new_path_len; #endif int ret; if (plugin == NULL) return -1; if (strlen(plugin) == 0) return 0; #ifndef __MINGW32__ /* * Add current dir to PATH, so we can search plugin in current dir */ env = cork_env_clone_current(); current_path = cork_env_get(env, "PATH"); if (current_path != NULL) { #ifdef HAVE_GET_CURRENT_DIR_NAME char *cwd = get_current_dir_name(); if (cwd) { #else char cwd[PATH_MAX]; if (!getcwd(cwd, PATH_MAX)) { #endif new_path_len = strlen(current_path) + strlen(cwd) + 2; new_path = ss_malloc(new_path_len); snprintf(new_path, new_path_len, "%s:%s", cwd, current_path); #ifdef HAVE_GET_CURRENT_DIR_NAME free(cwd); #endif } } if (new_path != NULL) cork_env_add(env, "PATH", new_path); #else sub_control_port = control_port; #endif if (!strncmp(plugin, "obfsproxy", strlen("obfsproxy"))) ret = start_obfsproxy(plugin, plugin_opts, remote_host, remote_port, local_host, local_port, mode); else ret = start_ss_plugin(plugin, plugin_opts, remote_host, remote_port, local_host, local_port, mode); #ifndef __MINGW32__ ss_free(new_path); #endif env = NULL; return ret; } uint16_t get_local_port() { int sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { return 0; } struct sockaddr_in serv_addr; bzero((char *)&serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = 0; if (bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { return 0; } socklen_t len = sizeof(serv_addr); if (getsockname(sock, (struct sockaddr *)&serv_addr, &len) == -1) { return 0; } if (close(sock) < 0) { return 0; } return ntohs(serv_addr.sin_port); } void stop_plugin() { if (sub != NULL) { cork_subprocess_abort(sub); cork_subprocess_free(sub); } } int is_plugin_running() { if (sub != NULL) { return cork_subprocess_is_finished(sub); } return 0; }
int start_plugin(const char *plugin, const char *plugin_opts, const char *remote_host, const char *remote_port, const char *local_host, const char *local_port) { char *new_path = NULL; char *cmd = NULL; if (plugin == NULL) return -1; if (strlen(plugin) == 0) return 0; size_t plugin_len = strlen(plugin); size_t cmd_len = plugin_len + CMD_RESRV_LEN; cmd = ss_malloc(cmd_len); snprintf(cmd, cmd_len, "exec %s", plugin); env = cork_env_clone_current(); const char *path = cork_env_get(env, "PATH"); if (path != NULL) { #ifdef __GLIBC__ char *cwd = get_current_dir_name(); if (cwd) { #else char cwd[PATH_MAX]; if (!getcwd(cwd, PATH_MAX)) { #endif size_t path_len = strlen(path) + strlen(cwd) + 2; new_path = ss_malloc(path_len); snprintf(new_path, path_len, "%s:%s", cwd, path); #ifdef __GLIBC__ free(cwd); #endif } } if (new_path != NULL) cork_env_add(env, "PATH", new_path); cork_env_add(env, "SS_REMOTE_HOST", remote_host); cork_env_add(env, "SS_REMOTE_PORT", remote_port); cork_env_add(env, "SS_LOCAL_HOST", local_host); cork_env_add(env, "SS_LOCAL_PORT", local_port); if (plugin_opts != NULL) cork_env_add(env, "SS_PLUGIN_OPTIONS", plugin_opts); exec = cork_exec_new_with_params("sh", "-c", cmd, NULL); cork_exec_set_env(exec, env); sub = cork_subprocess_new_exec(exec, NULL, NULL, &exit_code); int err = cork_subprocess_start(sub); ss_free(cmd); if (new_path != NULL) ss_free(new_path); return err; } uint16_t get_local_port() { int sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { return 0; } struct sockaddr_in serv_addr; bzero((char *) &serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = 0; if (bind(sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { return 0; } socklen_t len = sizeof(serv_addr); if (getsockname(sock, (struct sockaddr *)&serv_addr, &len) == -1) { return 0; } if (close (sock) < 0) { return 0; } return ntohs(serv_addr.sin_port); } void stop_plugin() { if (sub != NULL) { cork_subprocess_abort(sub); cork_subprocess_free(sub); } } int is_plugin_running() { if (sub != NULL) { return cork_subprocess_is_finished(sub); } return 0; }