예제 #1
0
static void
filter_dispatch(struct mproc *p, struct imsg *imsg)
{
	struct filter_session	*s;
	struct filter_connect	 q_connect;
	struct mailaddr		 maddr;
	struct msg		 m;
	const char		*line, *name;
	uint32_t		 v, datalen;
	uint64_t		 id, qid;
	int			 status, type;
	int			 fds[2], fdin, fdout;

	log_trace(TRACE_FILTERS, "filter-api:%s imsg %s", filter_name,
	    filterimsg_to_str(imsg->hdr.type));

	switch (imsg->hdr.type) {
	case IMSG_FILTER_REGISTER:
		m_msg(&m, imsg);
		m_get_u32(&m, &v);
		m_get_string(&m, &name);
		filter_name = strdup(name);
		m_end(&m);
		if (v != FILTER_API_VERSION) {
			log_warnx("warn: filter-api:%s API mismatch", filter_name);
			fatalx("filter-api: exiting");
		}
		m_create(p, IMSG_FILTER_REGISTER, 0, 0, -1);
		m_add_int(p, fi.hooks);
		m_add_int(p, fi.flags);
		m_close(p);
		break;

	case IMSG_FILTER_EVENT:
		m_msg(&m, imsg);
		m_get_id(&m, &id);
		m_get_int(&m, &type);
		m_end(&m);
		switch (type) {
		case EVENT_CONNECT:
			s = xcalloc(1, sizeof(*s), "filter_dispatch");
			s->id = id;
			s->pipe.iev.sock = -1;
			s->pipe.oev.sock = -1;
			tree_xset(&sessions, id, s);
			break;
		case EVENT_DISCONNECT:
			filter_dispatch_disconnect(id);
			s = tree_xpop(&sessions, id);
			free(s);
			break;
		case EVENT_RESET:
			filter_dispatch_reset(id);
			break;
		case EVENT_COMMIT:
			filter_dispatch_commit(id);
			break;
		case EVENT_ROLLBACK:
			filter_dispatch_rollback(id);
			break;
		default:
			log_warnx("warn: filter-api:%s bad event %d", filter_name, type);
			fatalx("filter-api: exiting");
		}
		break;

	case IMSG_FILTER_QUERY:
		m_msg(&m, imsg);
		m_get_id(&m, &id);
		m_get_id(&m, &qid);
		m_get_int(&m, &type);
		switch(type) {
		case QUERY_CONNECT:
			m_get_sockaddr(&m, (struct sockaddr*)&q_connect.local);
			m_get_sockaddr(&m, (struct sockaddr*)&q_connect.remote);
			m_get_string(&m, &q_connect.hostname);
			m_end(&m);
			filter_register_query(id, qid, type);
			filter_dispatch_connect(id, &q_connect);
			break;
		case QUERY_HELO:
			m_get_string(&m, &line);
			m_end(&m);
			filter_register_query(id, qid, type);
			filter_dispatch_helo(id, line);
			break;
		case QUERY_MAIL:
			m_get_mailaddr(&m, &maddr);
			m_end(&m);
			filter_register_query(id, qid, type);
			filter_dispatch_mail(id, &maddr);
			break;
		case QUERY_RCPT:
			m_get_mailaddr(&m, &maddr);
			m_end(&m);
			filter_register_query(id, qid, type);
			filter_dispatch_rcpt(id, &maddr);
			break;
		case QUERY_DATA:
			m_end(&m);
			filter_register_query(id, qid, type);
			filter_dispatch_data(id);
			break;
		case QUERY_EOM:
			m_get_u32(&m, &datalen);
			m_end(&m);
			filter_register_query(id, qid, type);
			filter_dispatch_eom(id, datalen);
			break;
		default:
			log_warnx("warn: filter-api:%s bad query %d", filter_name, type);
			fatalx("filter-api: exiting");
		}
		break;

	case IMSG_FILTER_PIPE:
		m_msg(&m, imsg);
		m_get_id(&m, &id);
		m_end(&m);

		fdout = imsg->fd;
		fdin = -1;

		if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, fds) == -1) {
			log_warn("warn: filter-api:%s socketpair", filter_name);
			close(fdout);
		}
		else {
			s = tree_xget(&sessions, id);

			s->pipe.eom_called = 0;
			s->pipe.error = 0;
			s->pipe.idatalen = 0;
			s->pipe.odatalen = 0;

			iobuf_init(&s->pipe.obuf, 0, 0);
			io_init(&s->pipe.oev, fdout, s, filter_io_out, &s->pipe.obuf);
			io_set_write(&s->pipe.oev);

			iobuf_init(&s->pipe.ibuf, 0, 0);
			io_init(&s->pipe.iev, fds[0], s, filter_io_in, &s->pipe.ibuf);
			io_set_read(&s->pipe.iev);

			fdin = fds[1];
		}

		log_trace(TRACE_FILTERS, "filter-api:%s %016"PRIx64" tx pipe %d -> %d",
		    filter_name, id, fdin, fdout);

		m_create(&fi.p, IMSG_FILTER_PIPE, 0, 0, fdin);
		m_add_id(&fi.p, id);
		m_close(&fi.p);

		break;
	}
}
예제 #2
0
static void
filter_dispatch(struct mproc *p, struct imsg *imsg)
{
	struct filter_connect	 q_connect;
	struct mailaddr		 maddr;
	struct msg		 m;
	const char		*line;
	uint32_t		 v;
	uint64_t		 id, qid;
	int			 status, event, hook;

	log_debug("debug: %s: imsg %i", filter_name, imsg->hdr.type);

	switch (imsg->hdr.type) {
	case IMSG_FILTER_REGISTER:
		m_msg(&m, imsg);
		m_get_u32(&m, &v);
		m_end(&m);
		if (v != FILTER_API_VERSION)
			errx(1, "API version mismatch");
		m_create(p, IMSG_FILTER_REGISTER, 0, 0, -1);
		m_add_int(p, fi.hooks);
		m_add_int(p, fi.flags);
		m_close(p);
		break;

	case IMSG_FILTER_EVENT:
		m_msg(&m, imsg);
		m_get_id(&m, &id);
		m_get_int(&m, &event);
		m_end(&m);
		filter_dispatch_event(id, event);
		break;

	case IMSG_FILTER_QUERY:
		m_msg(&m, imsg);
		m_get_id(&m, &id);
		m_get_id(&m, &qid);
		m_get_int(&m, &hook);
		tree_xset(&queries, qid, NULL);
		switch(hook) {
		case HOOK_CONNECT:
			m_get_sockaddr(&m, (struct sockaddr*)&q_connect.local);
			m_get_sockaddr(&m, (struct sockaddr*)&q_connect.remote);
			m_get_string(&m, &q_connect.hostname);
			m_end(&m);
			filter_dispatch_connect(id, qid, &q_connect);
			break;
		case HOOK_HELO:
			m_get_string(&m, &line);
			m_end(&m);
			filter_dispatch_helo(id, qid, line);
			break;
		case HOOK_MAIL:
			m_get_mailaddr(&m, &maddr);
			m_end(&m);
			filter_dispatch_mail(id, qid, &maddr);
			break;
		case HOOK_RCPT:
			m_get_mailaddr(&m, &maddr);
			m_end(&m);
			filter_dispatch_rcpt(id, qid, &maddr);
			break;
		case HOOK_DATA:
			m_end(&m);
			filter_dispatch_data(id, qid);
			break;
		case HOOK_EOM:
			m_end(&m);
			filter_dispatch_eom(id, qid);
			break;
		default:
			errx(1, "bad query hook: %d", hook);
		}
		break;

	case IMSG_FILTER_NOTIFY:
		m_msg(&m, imsg);
		m_get_id(&m, &qid);
		m_get_int(&m, &status);
		m_end(&m);
		filter_dispatch_notify(qid, status);
		break;

	case IMSG_FILTER_DATA:
		m_msg(&m, imsg);
		m_get_id(&m, &id);
		m_get_string(&m, &line);
		m_end(&m);
		filter_dispatch_dataline(id, line);
		break;
	}
}
예제 #3
0
static void
mfa_imsg(struct mproc *p, struct imsg *imsg)
{
	struct sockaddr_storage	 local, remote;
	struct mailaddr		 maddr;
	struct msg		 m;
	const char		*line, *hostname;
	uint64_t		 reqid;
	int			 v;

	if (p->proc == PROC_SMTP) {
		switch (imsg->hdr.type) {
		case IMSG_MFA_REQ_CONNECT:
			m_msg(&m, imsg);
			m_get_id(&m, &reqid);
			m_get_sockaddr(&m, (struct sockaddr *)&local);
			m_get_sockaddr(&m, (struct sockaddr *)&remote);
			m_get_string(&m, &hostname);
			m_end(&m);
			mfa_filter_connect(reqid, (struct sockaddr *)&local,
			    (struct sockaddr *)&remote, hostname);
			return;

		case IMSG_MFA_REQ_HELO:
			m_msg(&m, imsg);
			m_get_id(&m, &reqid);
			m_get_string(&m, &line);
			m_end(&m);
			mfa_filter_line(reqid, HOOK_HELO, line);
			return;

		case IMSG_MFA_REQ_MAIL:
			m_msg(&m, imsg);
			m_get_id(&m, &reqid);
			m_get_mailaddr(&m, &maddr);
			m_end(&m);
			mfa_filter_mailaddr(reqid, HOOK_MAIL, &maddr);
			return;

		case IMSG_MFA_REQ_RCPT:
			m_msg(&m, imsg);
			m_get_id(&m, &reqid);
			m_get_mailaddr(&m, &maddr);
			m_end(&m);
			mfa_filter_mailaddr(reqid, HOOK_RCPT, &maddr);
			return;

		case IMSG_MFA_REQ_DATA:
			m_msg(&m, imsg);
			m_get_id(&m, &reqid);
			m_end(&m);
			mfa_filter(reqid, HOOK_DATA);
			return;

		case IMSG_MFA_REQ_EOM:
			m_msg(&m, imsg);
			m_get_id(&m, &reqid);
			m_end(&m);
			mfa_filter(reqid, HOOK_EOM);
			return;

		case IMSG_MFA_SMTP_DATA:
			m_msg(&m, imsg);
			m_get_id(&m, &reqid);
			m_get_string(&m, &line);
			m_end(&m);
			mfa_filter_data(reqid, line);
			return;

		case IMSG_MFA_EVENT_RSET:
			m_msg(&m, imsg);
			m_get_id(&m, &reqid);
			m_end(&m);
			mfa_filter_event(reqid, HOOK_RESET);
			return;

		case IMSG_MFA_EVENT_COMMIT:
			m_msg(&m, imsg);
			m_get_id(&m, &reqid);
			m_end(&m);
			mfa_filter_event(reqid, HOOK_COMMIT);
			return;

		case IMSG_MFA_EVENT_ROLLBACK:
			m_msg(&m, imsg);
			m_get_id(&m, &reqid);
			m_end(&m);
			mfa_filter_event(reqid, HOOK_ROLLBACK);
			return;

		case IMSG_MFA_EVENT_DISCONNECT:
			m_msg(&m, imsg);
			m_get_id(&m, &reqid);
			m_end(&m);
			mfa_filter_event(reqid, HOOK_DISCONNECT);
			return;
		}
	}

	if (p->proc == PROC_PARENT) {
		switch (imsg->hdr.type) {
		case IMSG_CONF_START:
			return;

		case IMSG_CONF_FILTER:
			return;

		case IMSG_CONF_END:
			mfa_filter_init();
			return;
			
		case IMSG_CTL_VERBOSE:
			m_msg(&m, imsg);
			m_get_int(&m, &v);
			m_end(&m);
			log_verbose(v);
			return;

		case IMSG_CTL_PROFILE:
			m_msg(&m, imsg);
			m_get_int(&m, &v);
			m_end(&m);
			profiling = v;
			return;
		}
	}

	errx(1, "mfa_imsg: unexpected %s imsg", imsg_to_str(imsg->hdr.type));
}