Example #1
0
static int
runner_process_envelope(u_int64_t evpid)
{
	struct envelope	 envelope;
	size_t		 mta_av, mda_av, bnc_av;
	struct scheduler_info	si;

	mta_av = env->sc_maxconn - stat_get(STATS_MTA_SESSION, STAT_ACTIVE);
	mda_av = env->sc_maxconn - stat_get(STATS_MDA_SESSION, STAT_ACTIVE);
	bnc_av = env->sc_maxconn - stat_get(STATS_RUNNER_BOUNCES, STAT_ACTIVE);

	if (! queue_envelope_load(evpid, &envelope))
		return 0;

	if (envelope.type == D_MDA)
		if (mda_av == 0) {
			env->sc_flags |= SMTPD_MDA_BUSY;
			return 0;
		}

	if (envelope.type == D_MTA)
		if (mta_av == 0) {
			env->sc_flags |= SMTPD_MTA_BUSY;
			return 0;
		}

	if (envelope.type == D_BOUNCE)
		if (bnc_av == 0) {
			env->sc_flags |= SMTPD_BOUNCE_BUSY;
			return 0;
		}

	if (runner_check_loop(&envelope)) {
		struct envelope bounce;

		envelope_set_errormsg(&envelope, "loop has been detected");
		if (bounce_record_message(&envelope, &bounce)) {
			scheduler_info(&si, &bounce);
			scheduler->insert(&si);
		}
		scheduler->remove(evpid);
		queue_envelope_delete(&envelope);

		runner_reset_events();

		return 0;
	}


	return runner_process_batch(envelope.type, evpid);
}
Example #2
0
int stat_open(struct pk_state *state, const char *name)
{
	gchar *buf;
	int fh;

	buf = stat_get(state, name);
	if (buf == NULL)
		return -ENOENT;
	g_mutex_lock(state->fuse->stat_buffer_lock);
	/* Find the next available file handle */
	for (fh = 1; g_hash_table_lookup(state->fuse->stat_buffers,
				GINT_TO_POINTER(fh)); fh++);
	g_hash_table_insert(state->fuse->stat_buffers, GINT_TO_POINTER(fh),
				buf);
	g_mutex_unlock(state->fuse->stat_buffer_lock);
	return fh;
}
Example #3
0
static void
stat_print(int stat, int what)
{
	static const char *names[STATS_MAX] = {
		"smtp.sessions",
		"smtp.sessions.inet4",
		"smtp.sessions.inet6",
		"smtp.sessions.smtps",
		"smtp.sessions.starttls",

		"mta.sessions",

		"mda.sessions",

		"control.sessions",

		"lka.sessions",
		"lka.sessions.mx",
		"lka.sessions.host",
		"lka.sessions.cname",
		"lka.sessions.failure",

		"scheduler",
		"scheduler.bounces",

		"queue.inserts.local",
		"queue.inserts.remote",

		"ramqueue.envelopes",
		"ramqueue.messages",
		"ramqueue.batches",
		"ramqueue.hosts",
	};
	const char *sfx;

	if (what == STAT_ACTIVE)
		sfx = ".active";
	else if (what == STAT_MAXACTIVE)
		sfx = ".maxactive";
	else
		sfx = "";

	printf("%s%s=%zd\n", names[stat], sfx, stat_get(stat, what));
}
Example #4
0
void stat_shutdown(struct pk_state *state, gboolean normal)
{
	gchar **stats;
	gchar **cur;
	gchar *value;

	if (normal) {
		/* Log statistics */
		for (stats = cur = stat_list(state); *cur != NULL; cur++) {
			value = stat_get(state, *cur);
			g_strchomp(value);
			pk_log(LOG_STATS, "%s: %s", *cur, value);
			g_free(value);
		}
		g_strfreev(stats);
	}
	g_hash_table_destroy(state->fuse->stat_buffers);
	g_mutex_free(state->fuse->stat_buffer_lock);
}
Example #5
0
void
runner_imsg(struct imsgev *iev, struct imsg *imsg)
{
	struct envelope	*e, bounce;
	struct scheduler_info	si;

	log_imsg(PROC_RUNNER, iev->proc, imsg);

	switch (imsg->hdr.type) {
	case IMSG_QUEUE_COMMIT_MESSAGE:
		e = imsg->data;
		runner_message_to_scheduler(evpid_to_msgid(e->id));
		runner_reset_events();
		return;

	case IMSG_QUEUE_DELIVERY_OK:
		stat_decrement(STATS_RUNNER);
		e = imsg->data;
		log_debug("queue_delivery_ok: %016"PRIx64, e->id);
		scheduler->remove(e->id);
		queue_envelope_delete(e);
		return;

	case IMSG_QUEUE_DELIVERY_TEMPFAIL:
		stat_decrement(STATS_RUNNER);
		e = imsg->data;
		e->retry++;
		queue_envelope_update(e);
		log_debug("queue_delivery_tempfail: %016"PRIx64, e->id);
		scheduler_info(&si, e);
		scheduler->insert(&si);
		runner_reset_events();
		return;

	case IMSG_QUEUE_DELIVERY_PERMFAIL:
		stat_decrement(STATS_RUNNER);
		e = imsg->data;
		if (e->type != D_BOUNCE && e->sender.user[0] != '\0') {
			bounce_record_message(e, &bounce);
			log_debug("queue_delivery_permfail: %016"PRIx64,
			    bounce.id);
			scheduler_info(&si, &bounce);
			scheduler->insert(&si);
			runner_reset_events();
		}
		scheduler->remove(e->id);
		queue_envelope_delete(e);
		return;

	case IMSG_MDA_SESS_NEW:
		stat_decrement(STATS_MDA_SESSION);
		if (env->sc_maxconn - stat_get(STATS_MDA_SESSION, STAT_ACTIVE))
			env->sc_flags &= ~SMTPD_MDA_BUSY;
		runner_reset_events();
		return;

	case IMSG_BATCH_DONE:
		stat_decrement(STATS_MTA_SESSION);
		if (env->sc_maxconn - stat_get(STATS_MTA_SESSION, STAT_ACTIVE))
			env->sc_flags &= ~SMTPD_MTA_BUSY;
		runner_reset_events();
		return;

	case IMSG_SMTP_ENQUEUE:
		e = imsg->data;
		if (imsg->fd < 0 || !bounce_session(imsg->fd, e)) {
			queue_envelope_update(e);
			log_debug("smtp_enqueue: %016"PRIx64, e->id);
			scheduler_info(&si, e);
			scheduler->insert(&si);
			runner_reset_events();
			return;
		}
		return;

	case IMSG_QUEUE_PAUSE_MDA:
		env->sc_flags |= SMTPD_MDA_PAUSED;
		return;

	case IMSG_QUEUE_RESUME_MDA:
		env->sc_flags &= ~SMTPD_MDA_PAUSED;
		runner_reset_events();
		return;

	case IMSG_QUEUE_PAUSE_MTA:
		env->sc_flags |= SMTPD_MTA_PAUSED;
		return;

	case IMSG_QUEUE_RESUME_MTA:
		env->sc_flags &= ~SMTPD_MTA_PAUSED;
		runner_reset_events();
		return;

	case IMSG_CTL_VERBOSE:
		log_verbose(*(int *)imsg->data);
		return;

	case IMSG_RUNNER_SCHEDULE:
		scheduler->force(*(u_int64_t *)imsg->data);
		runner_reset_events();		
		return;

	case IMSG_RUNNER_REMOVE: {
		runner_remove(*(u_int64_t *)imsg->data);
		runner_reset_events();
		return;
	}
	}

	errx(1, "runner_imsg: unexpected %s imsg", imsg_to_str(imsg->hdr.type));
}
Example #6
0
int main(int argc, char **argv)  {

        int arg,ret;
	char *configfile;
	char pcapfile[256];

	// Load default config
	init_config();

        // Set the signal handlers
        signal(SIGHUP, sighup_handler);
        signal(SIGINT, sigquit_handler);
        signal(SIGQUIT,sigquit_handler);


        // Parse command-line options
        while ((arg = getopt(argc, argv, "IP:i:c:f:DqvdTsr:l:u:S:")) != -1){
                switch (arg){
                        case 'f':
                                strncpy(CONFIG_PCAP_FILTER,optarg,CONFIG_MAX_CHAR);
                                break;
			case 'r':
				strncpy(pcapfile,optarg,256);
				mode_offline=1;
				break;
			case 'c':
				configfile = optarg;
				read_config(configfile);
				//dump_config();
				break;
                        case 'i':
				// Start the pcap thread
                                strncpy(CONFIG_PCAP_DEV,optarg,CONFIG_MAX_CHAR);
                                break;
                        case 'P':
				CONFIG_DIVERT_PORT=atoi(optarg);
				break;
			case 'I':
				CONFIG_DIVERT_ENABLE=1;
                                break;
                        case 'q':
                                CONFIG_LOG_STDOUT = 0;
                                break;
                        case 'u':
				strncpy(CONFIG_USER,optarg,CONFIG_MAX_CHAR);
                                break;
                        case 'l':
                                strncpy(CONFIG_LOGDIR,optarg,CONFIG_MAX_CHAR);
				if(strlen(CONFIG_LOGDIR) > 64) {
					fatal_error("Log directory is too long!");
				}
				if (access(CONFIG_LOGDIR, F_OK) == -1){
					fatal_error("Log directory does not exist");
				}
                                break;
                        case 's':
                                CONFIG_LOG_SYSLOG = 1;
                                break;
			case 'S':
                                strncpy(CONFIG_SIGFILE,optarg,CONFIG_MAX_CHAR);
				break;
			case 'T':
				CONFIG_TCP_STRICT = 0;
				break;
                        case 'v':
                                CONFIG_LOG_VERBOSE++;
                                break;
			case 'd':
				CONFIG_SHOW_TRAFFIC = 1;
				break;
                        case 'D':
				fork_to_background(); 
                                break;
                        default:
				usage();
				exit(1);
                                break;
                }
        }

	// Initialize the stats structure and the streams
	stats_init();

        // Create the list, this is to store the IP packets in which can then
        // be read by another thread. TODO: add maximum list size
        trafficlist = getRingBuffer(CONFIG_RINGBUFFER_SIZE);

        // Register the destructor
        registerListDestructor(destructor_callback,trafficlist);
        registerListIterator(traffic_analyzer,trafficlist);

	// Create the control thread first for message logging
        pthread_create(&t_control,NULL,(void*)control_loop,NULL);

	//Initialize the detection hooks
	detect_hook_init();
	tcp_stream_init();

	//Initialize the timers
	timer_init();
	timer_register_function(CONFIG_TIMER_STATS,"Stats printer",stats_show_cnt_line,NULL);
	timer_register_function(CONFIG_TIMER_TCP_CLEANER,"TCP session cleaner", tcp_clean_sessions,NULL);
	timer_register_function(CONFIG_TIMER_IPFRAG_CLEANER,"IP fragment cleaner", ip_frag_cleaner,NULL);

	//Load the signatures
	if(load_signatures(CONFIG_SIGFILE) == 1){
		usage();
		exit(1);
	}

	// Make signature index;
	init_signature_indexes();

	log_info("Signatures loaded: %d, not loaded: %d", stat_get(CNT_SIG_LOADED), stat_get(CNT_SIG_NOT_LOADED));


	// Check if root privileges are required
	if(mode_offline == 0 && getuid() != 0) {
		fprintf(stderr, "Root privileges are required, unless you specify a\n");
		fprintf(stderr, "pcap file with the '-r' option..\n");
		exit(1);
	}

	if(CONFIG_DIVERT_ENABLE) {
		log_info("Opening DIVERT socket port: %d\n",CONFIG_DIVERT_PORT);
		divert_open_socket(CONFIG_DIVERT_PORT);

		// Start the divert_listen loop
		pthread_create(&t_listener,NULL,(void*)divert_listen_loop,handle);
	} else if(mode_offline != 1) {

		// If no device was specified AND not configured then the only
		// option is to pick one using the cap library (not recommended)
		if(*CONFIG_PCAP_DEV == '0') {
			if(pcap_return_device() != NULL) {
				log_info("Picking random interface (overrule -i)");
				strncpy(CONFIG_PCAP_DEV,pcap_return_device(),CONFIG_MAX_CHAR);
			} else {
					usage();
					exit(1);
			}
		}

		// Start the sniffer thread
		handle = pcap_open_device(CONFIG_PCAP_DEV,CONFIG_PCAP_FILTER);
		pthread_create(&t_listener,NULL,(void*)pcap_listen_loop,handle);
	} else {

		// Open the file
		handle = pcap_open_file(pcapfile,CONFIG_PCAP_FILTER);
		pthread_create(&t_listener,NULL,(void*)pcap_listen_loop,handle);
	}

	// Chroot if needed
	if(CONFIG_CHROOT_ENABLE == 1) {
		if((ret = chroot(CONFIG_CHROOT_DIR)) != 0) {
			fatal_error("Chroot to \"%s\" failed: %s !",CONFIG_CHROOT_DIR, strerror(errno));
		} else {
			log_info("Chroot to directory: \"%s\" done",CONFIG_CHROOT_DIR);
		}
	}

	// Drop privileges if needed
	if(*CONFIG_USER != '0' && drop_privileges(CONFIG_USER) != 0) {
		fatal_error("Unable to drop privileges, quitting for security reasons",CONFIG_USER);
	}

	// Set the time
	gettimeofday(&startuptime,NULL);
        pthread_create(&t_analyzer,NULL,(void*)pcap_analyzer,NULL);

	if(mode_offline == 1) {
		pthread_join(t_analyzer, NULL);
	} else {
		pthread_join(t_listener,NULL);
	}

	// Control thread
	loop_control = 0;
	pthread_join(t_control, NULL);

	// And bail out
	dump_stats(stdout);
        return 0;
}