Exemplo n.º 1
0
int
tor_init_libevent_rng(void)
{
  int rv = 0;
#ifdef HAVE_EVUTIL_SECURE_RNG_INIT
  char buf[256];
  if (evutil_secure_rng_init() < 0) {
    rv = -1;
  }
  /* Older libevent -- manually initialize the RNG */
  crypto_rand(buf, 32);
  evutil_secure_rng_add_bytes(buf, 32);
  evutil_secure_rng_get_bytes(buf, sizeof(buf));
#endif
  return rv;
}
Exemplo n.º 2
0
Arquivo: main.c Projeto: nexie/ed2kd
int main( int argc, char *argv[] )
{
        size_t i;
        int ret, opt, longIndex = 0;
        struct event *evsig_int;
#ifdef _WIN32
        WSADATA WSAData;
#endif
        pthread_t tcp_thread, *job_threads;

        if ( evutil_secure_rng_init() < 0 ) {
                ED2KD_LOGERR("failed to seed random number generator");
                return EXIT_FAILURE;
        }

        /* parse command line arguments */
        opt = getopt_long( argc, argv, optString, longOpts, &longIndex );
        while( opt != -1 ) {
                switch( opt ) {
                case 'v':
                        display_version();
                        return EXIT_SUCCESS;

                case 'g': {
                        unsigned char hash[ED2K_HASH_SIZE];
                        char hex_hash[sizeof(hash)*2+1];
                        get_random_user_hash(hash);
                        bin2hex(hash, hex_hash, sizeof(hex_hash));
                        puts(hex_hash);
                        return EXIT_SUCCESS;
                }

                case 'h':
                        display_usage();
                        return EXIT_SUCCESS;

                default:
                        return EXIT_FAILURE;
                }
                opt = getopt_long( argc, argv, optString, longOpts, &longIndex );
        }

#ifdef _WIN32
        if ( 0 != WSAStartup(0x0201, &WSAData) ) {
                ED2KD_LOGERR("WSAStartup failed!");
                return EXIT_FAILURE;
        }
#endif

        if ( !server_load_config(NULL) ) {
                ED2KD_LOGERR("failed to load configuration file");
                return EXIT_FAILURE;
        }

        display_libevent_info();

#ifdef EVTHREAD_USE_WINDOWS_THREADS_IMPLEMENTED
        ret = evthread_use_windows_threads();
#elif EVTHREAD_USE_PTHREADS_IMPLEMENTED
        ret = evthread_use_pthreads();
#else
#error "unable to determine threading model"
#endif
        if ( ret < 0 ) {
                ED2KD_LOGERR("failed to init libevent threading model");
                return EXIT_FAILURE;
        }

        g_srv.evbase_main = event_base_new();
        if ( NULL == g_srv.evbase_main ) {
                ED2KD_LOGERR("failed to create main event loop");
                return EXIT_FAILURE;
        }
        g_srv.evbase_tcp = event_base_new();
        if ( NULL == g_srv.evbase_tcp ) {
                ED2KD_LOGERR("failed to create tcp event loop");
                return EXIT_FAILURE;
        }

        evsig_int = evsignal_new(g_srv.evbase_main, SIGINT, sigint_cb, NULL);
        evsignal_add(evsig_int, NULL);

        // common timers timevals
        g_srv.portcheck_timeout_tv = event_base_init_common_timeout(g_srv.evbase_tcp, &g_srv.cfg->portcheck_timeout_tv);
        g_srv.status_notify_tv = event_base_init_common_timeout(g_srv.evbase_tcp, &g_srv.cfg->status_notify_tv);

        if ( !db_create() ) {
                ED2KD_LOGERR("failed to create database");
                return EXIT_FAILURE;
        }

        g_srv.thread_count = omp_get_num_procs() + 1;

        pthread_cond_init(&g_srv.job_cond, NULL);
        pthread_mutex_init(&g_srv.job_mutex, NULL);
        TAILQ_INIT(&g_srv.jqueue);

        job_threads = (pthread_t *)malloc(g_srv.thread_count * sizeof(*job_threads));

        // start tcp worker threads
        for ( i=0; i<g_srv.thread_count; ++i ) {
                pthread_create(&job_threads[i], NULL, server_job_worker, NULL);
        }

        // start tcp dispatch thread
        pthread_create(&tcp_thread, NULL, server_base_worker, g_srv.evbase_tcp);

        // start tcp listen loop
        if ( !server_listen() ) {
                ED2KD_LOGERR("failed to start server listener");
                server_stop();
        }

        pthread_join(tcp_thread, NULL);

        while ( EBUSY == pthread_cond_destroy(&g_srv.job_cond) ) {
                pthread_cond_broadcast(&g_srv.job_cond);
                //pthread_yield();
        }

        pthread_mutex_destroy(&g_srv.job_mutex);

        for ( i=0; i<g_srv.thread_count; ++i ) {
                pthread_join(job_threads[i], NULL);
        }

        free(job_threads);

        // todo: free job queue items

        evconnlistener_free(g_srv.tcp_listener);
        event_free(evsig_int);
        event_base_free(g_srv.evbase_tcp);
        event_base_free(g_srv.evbase_main);

        if ( db_destroy() < 0 ) {
                ED2KD_LOGERR("failed to destroy database");
        }

        server_free_config();

        return EXIT_SUCCESS;
}
Exemplo n.º 3
0
struct rspamd_worker *
rspamd_fork_worker (struct rspamd_main *rspamd_main,
		struct rspamd_worker_conf *cf,
		guint index,
		struct event_base *ev_base)
{
	struct rspamd_worker *wrk;
	gint rc;
	struct rlimit rlim;

	/* Starting worker process */
	wrk = (struct rspamd_worker *) g_malloc0 (sizeof (struct rspamd_worker));

	if (!rspamd_socketpair (wrk->control_pipe)) {
		msg_err ("socketpair failure: %s", strerror (errno));
		exit (-errno);
	}

	if (!rspamd_socketpair (wrk->srv_pipe)) {
		msg_err ("socketpair failure: %s", strerror (errno));
		exit (-errno);
	}

	wrk->srv = rspamd_main;
	wrk->type = cf->type;
	wrk->cf = cf;
	REF_RETAIN (cf);
	wrk->index = index;
	wrk->ctx = cf->ctx;
	wrk->finish_actions = g_ptr_array_new ();

	wrk->pid = fork ();

	switch (wrk->pid) {
	case 0:
		/* Update pid for logging */
		rspamd_log_update_pid (cf->type, rspamd_main->logger);

		/* Init PRNG after fork */
		rc = ottery_init (rspamd_main->cfg->libs_ctx->ottery_cfg);
		if (rc != OTTERY_ERR_NONE) {
			msg_err_main ("cannot initialize PRNG: %d", rc);
			abort ();
		}

		rspamd_random_seed_fast ();
#ifdef HAVE_EVUTIL_RNG_INIT
		evutil_secure_rng_init ();
#endif

		/* Remove the inherited event base */
		event_reinit (rspamd_main->ev_base);
		event_base_free (rspamd_main->ev_base);

		/* Drop privilleges */
		rspamd_worker_drop_priv (rspamd_main);
		/* Set limits */
		rspamd_worker_set_limits (rspamd_main, cf);
		/* Re-set stack limit */
		getrlimit (RLIMIT_STACK, &rlim);
		rlim.rlim_cur = 100 * 1024 * 1024;
		rlim.rlim_max = rlim.rlim_cur;
		setrlimit (RLIMIT_STACK, &rlim);

		setproctitle ("%s process", cf->worker->name);
		rspamd_pidfile_close (rspamd_main->pfh);
		/* Do silent log reopen to avoid collisions */
		rspamd_log_close (rspamd_main->logger);
		rspamd_log_open (rspamd_main->logger);
		wrk->start_time = rspamd_get_calendar_ticks ();

#if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION <= 30))
# if (GLIB_MINOR_VERSION > 20)
		/* Ugly hack for old glib */
		if (!g_thread_get_initialized ()) {
			g_thread_init (NULL);
		}
# else
		g_thread_init (NULL);
# endif
#endif
		msg_info_main ("starting %s process %P (%d)", cf->worker->name,
				getpid (), index);
		/* Close parent part of socketpair */
		close (wrk->control_pipe[0]);
		close (wrk->srv_pipe[0]);
		rspamd_socket_nonblocking (wrk->control_pipe[1]);
		rspamd_socket_nonblocking (wrk->srv_pipe[1]);
		/* Execute worker */
		cf->worker->worker_start_func (wrk);
		exit (EXIT_FAILURE);
		break;
	case -1:
		msg_err_main ("cannot fork main process. %s", strerror (errno));
		rspamd_pidfile_remove (rspamd_main->pfh);
		exit (-errno);
		break;
	default:
		/* Close worker part of socketpair */
		close (wrk->control_pipe[1]);
		close (wrk->srv_pipe[1]);
		rspamd_socket_nonblocking (wrk->control_pipe[0]);
		rspamd_socket_nonblocking (wrk->srv_pipe[0]);
		rspamd_srv_start_watching (wrk, ev_base);
		/* Insert worker into worker's table, pid is index */
		g_hash_table_insert (rspamd_main->workers, GSIZE_TO_POINTER (
				wrk->pid), wrk);
		break;
	}

	return wrk;
}
Exemplo n.º 4
0
static gint
lua_worker_spawn_process (lua_State *L)
{
	struct rspamd_worker *w = lua_check_worker (L, 1);
	struct rspamd_lua_process_cbdata *cbdata;
	struct rspamd_abstract_worker_ctx *actx;
	struct rspamd_srv_command srv_cmd;
	const gchar *cmdline = NULL, *input = NULL;
	gsize inputlen = 0;
	pid_t pid;
	GError *err = NULL;
	gint func_cbref, cb_cbref;

	if (!rspamd_lua_parse_table_arguments (L, 2, &err,
			"func=F;exec=S;stdin=V;*on_complete=F", &func_cbref,
			&cmdline, &inputlen, &input, &cb_cbref)) {
		msg_err ("cannot get parameters list: %e", err);

		if (err) {
			g_error_free (err);
		}

		return 0;
	}

	cbdata = g_malloc0 (sizeof (*cbdata));
	cbdata->cb_cbref = cb_cbref;
	cbdata->func_cbref = func_cbref;

	if (input) {
		cbdata->out_buf = g_string_new_len (input, inputlen);
		cbdata->out_pos = 0;
	}

	if (rspamd_socketpair (cbdata->sp, TRUE) == -1) {
		msg_err ("cannot spawn socketpair: %s", strerror (errno));
		luaL_unref (L, LUA_REGISTRYINDEX, cbdata->func_cbref);
		luaL_unref (L, LUA_REGISTRYINDEX, cbdata->cb_cbref);
		g_free (cbdata);

		return 0;
	}

	actx = w->ctx;
	cbdata->wrk = w;
	cbdata->L = L;
	cbdata->ev_base = actx->ev_base;
	cbdata->sz = (guint64)-1;

	pid = fork ();

	if (pid == -1) {
		msg_err ("cannot spawn process: %s", strerror (errno));
		close (cbdata->sp[0]);
		close (cbdata->sp[1]);
		luaL_unref (L, LUA_REGISTRYINDEX, cbdata->func_cbref);
		luaL_unref (L, LUA_REGISTRYINDEX, cbdata->cb_cbref);
		g_free (cbdata);

		return 0;
	}
	else if (pid == 0) {
		/* Child */
		gint rc;
		gchar inbuf[4];

		rspamd_log_update_pid (w->cf->type, w->srv->logger);
		rc = ottery_init (w->srv->cfg->libs_ctx->ottery_cfg);

		if (rc != OTTERY_ERR_NONE) {
			msg_err ("cannot initialize PRNG: %d", rc);
			abort ();
		}
		rspamd_random_seed_fast ();
#ifdef HAVE_EVUTIL_RNG_INIT
		evutil_secure_rng_init ();
#endif

		close (cbdata->sp[0]);
		/* Here we assume that we can block on writing results */
		rspamd_socket_blocking (cbdata->sp[1]);
		event_reinit (cbdata->ev_base);
		g_hash_table_remove_all (w->signal_events);
		rspamd_worker_unblock_signals ();
		rspamd_lua_execute_lua_subprocess (L, cbdata);

		/* Wait for parent to reply and exit */
		rc = read (cbdata->sp[1], inbuf, sizeof (inbuf));

		if (memcmp (inbuf, "\0\0\0\0", 4) == 0) {
			exit (EXIT_SUCCESS);
		}
		else {
			msg_err ("got invalid reply from parent");

			exit (EXIT_FAILURE);
		}

	}

	cbdata->cpid = pid;
	cbdata->io_buf = g_string_sized_new (8);
	/* Notify main */
	memset (&srv_cmd, 0, sizeof (srv_cmd));
	srv_cmd.type = RSPAMD_SRV_ON_FORK;
	srv_cmd.cmd.on_fork.state = child_create;
	srv_cmd.cmd.on_fork.cpid = pid;
	srv_cmd.cmd.on_fork.ppid = getpid ();
	rspamd_srv_send_command (w, cbdata->ev_base, &srv_cmd, -1, NULL, NULL);

	close (cbdata->sp[1]);
	rspamd_socket_nonblocking (cbdata->sp[0]);
	/* Parent */
	rspamd_worker_set_signal_handler (SIGCHLD, w, cbdata->ev_base,
			rspamd_lua_cld_handler,
			cbdata);

	/* Add result pipe waiting */
	event_set (&cbdata->ev, cbdata->sp[0], EV_READ | EV_PERSIST,
			rspamd_lua_subprocess_io, cbdata);
	event_base_set (cbdata->ev_base, &cbdata->ev);
	/* TODO: maybe add timeout? */
	event_add (&cbdata->ev, NULL);

	return 0;
}
Exemplo n.º 5
0
int main(int argc, char **argv)
{
	int error;
	app_subsys **ss;
	int exit_signals[2] = {SIGTERM, SIGINT};
	struct event terminators[2];
	bool conftest = false;
	int opt;
	int i;

	evutil_secure_rng_init();
	while ((opt = getopt(argc, argv, "h?vtc:p:")) != -1) {
		switch (opt) {
		case 't':
			conftest = true;
			break;
		case 'c':
			confname = optarg;
			break;
		case 'p':
			pidfile = optarg;
			break;
		case 'v':
			puts(redsocks_version);
			printf("Built with libevent-%s\n", LIBEVENT_VERSION);
			printf("Runs  with libevent-%s\n", event_get_version());
			if (LIBEVENT_VERSION_NUMBER != event_get_version_number()) {
				printf("Warning: libevent version number mismatch.\n"
				       "  Headers: %8x\n"
				       "  Runtime: %8x\n", LIBEVENT_VERSION_NUMBER, event_get_version_number());
			}
			return EXIT_SUCCESS;
		default:
			printf(
				"Usage: %s [-?hvt] [-c config] [-p pidfile]\n"
				"  -h, -?       this message\n"
				"  -v           print version\n"
				"  -t           test config syntax\n"
				"  -p           write pid to pidfile\n",
				argv[0]);
			return (opt == '?' || opt == 'h') ? EXIT_SUCCESS : EXIT_FAILURE;
		}
	}

	if (event_get_struct_event_size() != sizeof(struct event)) {
		puts("libevent event_get_struct_event_size() != sizeof(struct event)! Check `redsocks -v` and recompile redsocks");
		return EXIT_FAILURE;
	}

	FILE *f = fopen(confname, "r");
	if (!f) {
		perror("Unable to open config file");
		return EXIT_FAILURE;
	}

	parser_context* parser = parser_start(f);
	if (!parser) {
		perror("Not enough memory for parser");
		return EXIT_FAILURE;
	}

	FOREACH(ss, subsystems)
		if ((*ss)->conf_section)
			parser_add_section(parser, (*ss)->conf_section);
	error = parser_run(parser);
	parser_stop(parser);
	fclose(f);

	if (error)
		return EXIT_FAILURE;

	if (conftest)
		return EXIT_SUCCESS;

	struct event_base* evbase = event_init();
	memset(terminators, 0, sizeof(terminators));

	FOREACH(ss, subsystems) {
		if ((*ss)->init) {
			error = (*ss)->init(evbase);
			if (error)
				goto shutdown;
		}
	}

	if (pidfile) {
		f = fopen(pidfile, "w");
		if (!f) {
			perror("Unable to open pidfile for write");
			return EXIT_FAILURE;
		}
		fprintf(f, "%d\n", getpid());
		fclose(f);
	}

	assert(SIZEOF_ARRAY(exit_signals) == SIZEOF_ARRAY(terminators));
	for (i = 0; i < SIZEOF_ARRAY(exit_signals); i++) {
		signal_set(&terminators[i], exit_signals[i], terminate, NULL);
		if (signal_add(&terminators[i], NULL) != 0) {
			log_errno(LOG_ERR, "signal_add");
			goto shutdown;
		}
	}

	if (LIBEVENT_VERSION_NUMBER != event_get_version_number()) {
		log_error(LOG_WARNING, "libevent version mismatch! headers %8x, runtime %8x\n", LIBEVENT_VERSION_NUMBER, event_get_version_number());
	}

	log_error(LOG_NOTICE, "redsocks started, conn_max=%u", redsocks_conn_max());

	event_dispatch();

	log_error(LOG_NOTICE, "redsocks goes down");

shutdown:
	for (i = 0; i < SIZEOF_ARRAY(exit_signals); i++) {
		if (signal_initialized(&terminators[i])) {
			if (signal_del(&terminators[i]) != 0)
				log_errno(LOG_WARNING, "signal_del");
			memset(&terminators[i], 0, sizeof(terminators[i]));
		}
	}

	for (--ss; ss >= subsystems; ss--)
		if ((*ss)->fini)
			(*ss)->fini();

	event_base_free(evbase);

	return !error ? EXIT_SUCCESS : EXIT_FAILURE;
}