xref: /openbsd-src/usr.sbin/smtpd/config.c (revision a28daedfc357b214be5c701aa8ba8adb29a7f1c2)
1 /*	$OpenBSD: config.c,v 1.5 2009/02/16 12:10:25 jacekm Exp $	*/
2 
3 /*
4  * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/types.h>
20 #include <sys/queue.h>
21 #include <sys/tree.h>
22 #include <sys/param.h>
23 #include <sys/socket.h>
24 
25 #include <event.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <unistd.h>
29 
30 #include "smtpd.h"
31 
32 int	is_peer(struct peer *, enum smtp_proc_type, u_int);
33 
34 int
35 is_peer(struct peer *p, enum smtp_proc_type peer, u_int peercount)
36 {
37 	u_int	i;
38 
39 	for (i = 0; i < peercount; i++)
40 		if (p[i].id == peer)
41 			return (1);
42 	return (0);
43 }
44 
45 void
46 unconfigure(struct smtpd *env)
47 {
48 }
49 
50 void
51 configure(struct smtpd *env)
52 {
53 }
54 
55 void
56 purge_config(struct smtpd *env, u_int8_t what)
57 {
58 	struct listener	*l;
59 	struct map	*m;
60 	struct rule	*r;
61 	struct cond	*c;
62 	struct opt	*o;
63 	struct ssl	*s;
64 
65 	if (what & PURGE_LISTENERS) {
66 		while ((l = TAILQ_FIRST(&env->sc_listeners)) != NULL) {
67 			TAILQ_REMOVE(&env->sc_listeners, l, entry);
68 			free(l);
69 		}
70 		TAILQ_INIT(&env->sc_listeners);
71 	}
72 	if (what & PURGE_MAPS) {
73 		while ((m = TAILQ_FIRST(env->sc_maps)) != NULL) {
74 			TAILQ_REMOVE(env->sc_maps, m, m_entry);
75 			free(m);
76 		}
77 		free(env->sc_maps);
78 		env->sc_maps = NULL;
79 	}
80 	if (what & PURGE_RULES) {
81 		while ((r = TAILQ_FIRST(env->sc_rules)) != NULL) {
82 			TAILQ_REMOVE(env->sc_rules, r, r_entry);
83 			while ((c = TAILQ_FIRST(&r->r_conditions)) != NULL) {
84 				TAILQ_REMOVE(&r->r_conditions, c, c_entry);
85 				free(c);
86 			}
87 			while ((o = TAILQ_FIRST(&r->r_options)) != NULL) {
88 				TAILQ_REMOVE(&r->r_options, o, o_entry);
89 				free(o);
90 			}
91 			free(r);
92 		}
93 		env->sc_rules = NULL;
94 	}
95 	if (what & PURGE_SSL) {
96 		while ((s = SPLAY_ROOT(&env->sc_ssl)) != NULL) {
97 			SPLAY_REMOVE(ssltree, &env->sc_ssl, s);
98 			free(s->ssl_cert);
99 			free(s->ssl_key);
100 			free(s);
101 		}
102 		SPLAY_INIT(&env->sc_ssl);
103 	}
104 }
105 
106 void
107 init_peers(struct smtpd *env)
108 {
109 	int	 i;
110 	int	 j;
111 	int	 count;
112 	int	 sockpair[2];
113 
114 	for (i = 0; i < PROC_COUNT; i++)
115 		for (j = 0; j < PROC_COUNT; j++) {
116 			/*
117 			 * find out how many instances of this peer there are.
118 			 */
119 			if (i >= j || env->sc_instances[i] == 0||
120 			   env->sc_instances[j] == 0)
121 				continue;
122 
123 			if (env->sc_instances[i] > 1 &&
124 			    env->sc_instances[j] > 1)
125 				fatalx("N:N peering not supported");
126 
127 			count = env->sc_instances[i] * env->sc_instances[j];
128 
129 			if ((env->sc_pipes[i][j] =
130 			    calloc(count, sizeof(int))) == NULL ||
131 			    (env->sc_pipes[j][i] =
132 			    calloc(count, sizeof(int))) == NULL)
133 				fatal(NULL);
134 
135 			while (--count >= 0) {
136 				if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC,
137 				    sockpair) == -1)
138 					fatal("socketpair");
139 				env->sc_pipes[i][j][count] = sockpair[0];
140 				env->sc_pipes[j][i][count] = sockpair[1];
141 				session_socket_blockmode(
142 				    env->sc_pipes[i][j][count],
143 				    BM_NONBLOCK);
144 				session_socket_blockmode(
145 				    env->sc_pipes[j][i][count],
146 				    BM_NONBLOCK);
147 			}
148 		}
149 }
150 
151 void
152 config_pipes(struct smtpd *env, struct peer *p, u_int peercount)
153 {
154 	u_int	i;
155 	u_int	j;
156 	int	count;
157 
158 	/*
159 	 * close pipes
160 	 */
161 	for (i = 0; i < PROC_COUNT; i++) {
162 		for (j = 0; j < PROC_COUNT; j++) {
163 			if (i == j ||
164 			    env->sc_instances[i] == 0 ||
165 			    env->sc_instances[j] == 0)
166 				continue;
167 
168 			for (count = 0;
169 			    count < env->sc_instances[i]*env->sc_instances[j];
170 			    count++) {
171 				if (i == smtpd_process &&
172 				    is_peer(p, j, peercount) &&
173 				    count == env->sc_instance)
174 					continue;
175 				if (i == smtpd_process &&
176 				    is_peer(p, j, peercount) &&
177 				    env->sc_instances[i] == 1)
178 					continue;
179 				close(env->sc_pipes[i][j][count]);
180 				env->sc_pipes[i][j][count] = -1;
181 			}
182 		}
183 	}
184 }
185 
186 void
187 config_peers(struct smtpd *env, struct peer *p, u_int peercount)
188 {
189 	int	count;
190 	u_int	src;
191 	u_int	dst;
192 	u_int	i;
193 	/*
194 	 * listen on appropriate pipes
195 	 */
196 	for (i = 0; i < peercount; i++) {
197 
198 		src = smtpd_process;
199 		dst = p[i].id;
200 
201 		if (dst == smtpd_process)
202 			fatal("config_peers: cannot peer with oneself");
203 
204 		if ((env->sc_ibufs[dst] = calloc(env->sc_instances[dst],
205 		    sizeof(struct imsgbuf))) == NULL)
206 			fatal("config_peers");
207 
208 		for (count = 0; count < env->sc_instances[dst]; count++) {
209 			imsg_init(&(env->sc_ibufs[dst][count]),
210 			    env->sc_pipes[src][dst][count], p[i].cb);
211 
212 			env->sc_ibufs[dst][count].events = EV_READ;
213 			env->sc_ibufs[dst][count].data = env;
214 
215 			event_set(&(env->sc_ibufs[dst][count].ev),
216 			    env->sc_ibufs[dst][count].fd,
217 			    env->sc_ibufs[dst][count].events,
218 			    env->sc_ibufs[dst][count].handler,
219 			    env->sc_ibufs[dst][count].data);
220 			event_add(&(env->sc_ibufs[dst][count].ev), NULL);
221 		}
222 	}
223 }
224