aboutsummaryrefslogtreecommitdiffstats
path: root/smtpd/config.c
diff options
context:
space:
mode:
authorGilles Chehade <gilles@poolp.org>2012-10-29 16:25:57 +0100
committerGilles Chehade <gilles@poolp.org>2012-10-29 16:25:57 +0100
commitc899adf7daeda5c079c0aee41cbff858ffed64a6 (patch)
tree5e2f406a595fa998adace2af6aab19f29ee1021d /smtpd/config.c
parentLimit the number of messages that can be enqueued on a single SMTP (diff)
downloadOpenSMTPD-c899adf7daeda5c079c0aee41cbff858ffed64a6.tar.xz
OpenSMTPD-c899adf7daeda5c079c0aee41cbff858ffed64a6.zip
move to new layout
Diffstat (limited to 'smtpd/config.c')
-rw-r--r--smtpd/config.c222
1 files changed, 222 insertions, 0 deletions
diff --git a/smtpd/config.c b/smtpd/config.c
new file mode 100644
index 00000000..fcc0c90f
--- /dev/null
+++ b/smtpd/config.c
@@ -0,0 +1,222 @@
+/* $OpenBSD: config.c,v 1.16 2012/08/19 14:16:57 chl Exp $ */
+
+/*
+ * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/tree.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <event.h>
+#include <imsg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "smtpd.h"
+#include "log.h"
+
+static int is_peer(struct peer *, enum smtp_proc_type, uint);
+
+static int
+is_peer(struct peer *p, enum smtp_proc_type peer, uint peercount)
+{
+ uint i;
+
+ for (i = 0; i < peercount; i++)
+ if (p[i].id == peer)
+ return (1);
+ return (0);
+}
+
+void
+unconfigure(void)
+{
+}
+
+void
+configure(void)
+{
+}
+
+void
+purge_config(uint8_t what)
+{
+ struct listener *l;
+ struct map *m;
+ struct rule *r;
+ struct ssl *s;
+ struct mapel *me;
+
+ if (what & PURGE_LISTENERS) {
+ while ((l = TAILQ_FIRST(env->sc_listeners)) != NULL) {
+ TAILQ_REMOVE(env->sc_listeners, l, entry);
+ free(l);
+ }
+ free(env->sc_listeners);
+ env->sc_listeners = NULL;
+ }
+ if (what & PURGE_MAPS) {
+ while ((m = TAILQ_FIRST(env->sc_maps)) != NULL) {
+ TAILQ_REMOVE(env->sc_maps, m, m_entry);
+ while ((me = TAILQ_FIRST(&m->m_contents))) {
+ TAILQ_REMOVE(&m->m_contents, me, me_entry);
+ free(me);
+ }
+ free(m);
+ }
+ free(env->sc_maps);
+ env->sc_maps = NULL;
+ }
+ if (what & PURGE_RULES) {
+ while ((r = TAILQ_FIRST(env->sc_rules)) != NULL) {
+ TAILQ_REMOVE(env->sc_rules, r, r_entry);
+ free(r);
+ }
+ free(env->sc_rules);
+ env->sc_rules = NULL;
+ }
+ if (what & PURGE_SSL) {
+ while ((s = SPLAY_ROOT(env->sc_ssl)) != NULL) {
+ SPLAY_REMOVE(ssltree, env->sc_ssl, s);
+ free(s->ssl_cert);
+ free(s->ssl_key);
+ free(s);
+ }
+ free(env->sc_ssl);
+ env->sc_ssl = NULL;
+ }
+}
+
+void
+init_pipes(void)
+{
+ int i;
+ int j;
+ int count;
+ int sockpair[2];
+
+ for (i = 0; i < PROC_COUNT; i++)
+ for (j = 0; j < PROC_COUNT; j++) {
+ /*
+ * find out how many instances of this peer there are.
+ */
+ if (i >= j || env->sc_instances[i] == 0||
+ env->sc_instances[j] == 0)
+ continue;
+
+ if (env->sc_instances[i] > 1 &&
+ env->sc_instances[j] > 1)
+ fatalx("N:N peering not supported");
+
+ count = env->sc_instances[i] * env->sc_instances[j];
+
+ env->sc_pipes[i][j] = xcalloc(count, sizeof(int),
+ "init_pipes");
+ env->sc_pipes[j][i] = xcalloc(count, sizeof(int),
+ "init_pipes");
+
+ while (--count >= 0) {
+ if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC,
+ sockpair) == -1)
+ fatal("socketpair");
+ env->sc_pipes[i][j][count] = sockpair[0];
+ env->sc_pipes[j][i][count] = sockpair[1];
+ session_socket_blockmode(
+ env->sc_pipes[i][j][count],
+ BM_NONBLOCK);
+ session_socket_blockmode(
+ env->sc_pipes[j][i][count],
+ BM_NONBLOCK);
+ }
+ }
+}
+
+void
+config_pipes(struct peer *p, uint peercount)
+{
+ uint i;
+ uint j;
+ int count;
+
+ /*
+ * close pipes
+ */
+ for (i = 0; i < PROC_COUNT; i++) {
+ for (j = 0; j < PROC_COUNT; j++) {
+ if (i == j ||
+ env->sc_instances[i] == 0 ||
+ env->sc_instances[j] == 0)
+ continue;
+
+ for (count = 0;
+ count < env->sc_instances[i]*env->sc_instances[j];
+ count++) {
+ if (i == smtpd_process &&
+ is_peer(p, j, peercount) &&
+ count == env->sc_instance)
+ continue;
+ if (i == smtpd_process &&
+ is_peer(p, j, peercount) &&
+ env->sc_instances[i] == 1)
+ continue;
+ close(env->sc_pipes[i][j][count]);
+ env->sc_pipes[i][j][count] = -1;
+ }
+ }
+ }
+}
+
+void
+config_peers(struct peer *p, uint peercount)
+{
+ int count;
+ uint src;
+ uint dst;
+ uint i;
+ /*
+ * listen on appropriate pipes
+ */
+ for (i = 0; i < peercount; i++) {
+
+ src = smtpd_process;
+ dst = p[i].id;
+
+ if (dst == smtpd_process)
+ fatal("config_peers: cannot peer with oneself");
+
+ env->sc_ievs[dst] = xcalloc(env->sc_instances[dst],
+ sizeof(struct imsgev), "config_peers");
+
+ for (count = 0; count < env->sc_instances[dst]; count++) {
+ imsg_init(&(env->sc_ievs[dst][count].ibuf),
+ env->sc_pipes[src][dst][count]);
+ env->sc_ievs[dst][count].handler = p[i].cb;
+ env->sc_ievs[dst][count].events = EV_READ;
+ env->sc_ievs[dst][count].proc = dst;
+ env->sc_ievs[dst][count].data = &env->sc_ievs[dst][count];
+
+ event_set(&(env->sc_ievs[dst][count].ev),
+ env->sc_ievs[dst][count].ibuf.fd,
+ env->sc_ievs[dst][count].events,
+ env->sc_ievs[dst][count].handler,
+ env->sc_ievs[dst][count].data);
+ event_add(&(env->sc_ievs[dst][count].ev), NULL);
+ }
+ }
+}