xref: /openbsd-src/usr.sbin/smtpd/mta.c (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1 /*	$OpenBSD: mta.c,v 1.202 2016/09/03 22:59:06 giovanni Exp $	*/
2 
3 /*
4  * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
5  * Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
6  * Copyright (c) 2009 Jacek Masiulaniec <jacekm@dobremiasto.net>
7  * Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
8  *
9  * Permission to use, copy, modify, and distribute this software for any
10  * purpose with or without fee is hereby granted, provided that the above
11  * copyright notice and this permission notice appear in all copies.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20  */
21 
22 #include <sys/types.h>
23 #include <sys/queue.h>
24 #include <sys/tree.h>
25 #include <sys/socket.h>
26 
27 #include <ctype.h>
28 #include <err.h>
29 #include <errno.h>
30 #include <event.h>
31 #include <imsg.h>
32 #include <inttypes.h>
33 #include <netdb.h>
34 #include <limits.h>
35 #include <pwd.h>
36 #include <signal.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <time.h>
41 #include <unistd.h>
42 
43 #include "smtpd.h"
44 #include "log.h"
45 
46 #define MAXERROR_PER_ROUTE	4
47 
48 #define DELAY_CHECK_SOURCE	1
49 #define DELAY_CHECK_SOURCE_SLOW	10
50 #define DELAY_CHECK_SOURCE_FAST 0
51 #define DELAY_CHECK_LIMIT	5
52 
53 #define	DELAY_QUADRATIC		1
54 #define DELAY_ROUTE_BASE	15
55 #define DELAY_ROUTE_MAX		3600
56 
57 #define RELAY_ONHOLD		0x01
58 #define RELAY_HOLDQ		0x02
59 
60 static void mta_query_mx(struct mta_relay *);
61 static void mta_query_secret(struct mta_relay *);
62 static void mta_query_preference(struct mta_relay *);
63 static void mta_query_source(struct mta_relay *);
64 static void mta_on_mx(void *, void *, void *);
65 static void mta_on_secret(struct mta_relay *, const char *);
66 static void mta_on_preference(struct mta_relay *, int);
67 static void mta_on_source(struct mta_relay *, struct mta_source *);
68 static void mta_on_timeout(struct runq *, void *);
69 static void mta_connect(struct mta_connector *);
70 static void mta_route_enable(struct mta_route *);
71 static void mta_route_disable(struct mta_route *, int, int);
72 static void mta_drain(struct mta_relay *);
73 static void mta_delivery_flush_event(int, short, void *);
74 static void mta_flush(struct mta_relay *, int, const char *);
75 static struct mta_route *mta_find_route(struct mta_connector *, time_t, int*,
76     time_t*);
77 static void mta_log(const struct mta_envelope *, const char *, const char *,
78     const char *, const char *);
79 
80 SPLAY_HEAD(mta_relay_tree, mta_relay);
81 static struct mta_relay *mta_relay(struct envelope *);
82 static void mta_relay_ref(struct mta_relay *);
83 static void mta_relay_unref(struct mta_relay *);
84 static void mta_relay_show(struct mta_relay *, struct mproc *, uint32_t, time_t);
85 static int mta_relay_cmp(const struct mta_relay *, const struct mta_relay *);
86 SPLAY_PROTOTYPE(mta_relay_tree, mta_relay, entry, mta_relay_cmp);
87 
88 SPLAY_HEAD(mta_host_tree, mta_host);
89 static struct mta_host *mta_host(const struct sockaddr *);
90 static void mta_host_ref(struct mta_host *);
91 static void mta_host_unref(struct mta_host *);
92 static int mta_host_cmp(const struct mta_host *, const struct mta_host *);
93 SPLAY_PROTOTYPE(mta_host_tree, mta_host, entry, mta_host_cmp);
94 
95 SPLAY_HEAD(mta_domain_tree, mta_domain);
96 static struct mta_domain *mta_domain(char *, int);
97 #if 0
98 static void mta_domain_ref(struct mta_domain *);
99 #endif
100 static void mta_domain_unref(struct mta_domain *);
101 static int mta_domain_cmp(const struct mta_domain *, const struct mta_domain *);
102 SPLAY_PROTOTYPE(mta_domain_tree, mta_domain, entry, mta_domain_cmp);
103 
104 SPLAY_HEAD(mta_source_tree, mta_source);
105 static struct mta_source *mta_source(const struct sockaddr *);
106 static void mta_source_ref(struct mta_source *);
107 static void mta_source_unref(struct mta_source *);
108 static const char *mta_source_to_text(struct mta_source *);
109 static int mta_source_cmp(const struct mta_source *, const struct mta_source *);
110 SPLAY_PROTOTYPE(mta_source_tree, mta_source, entry, mta_source_cmp);
111 
112 static struct mta_connector *mta_connector(struct mta_relay *,
113     struct mta_source *);
114 static void mta_connector_free(struct mta_connector *);
115 static const char *mta_connector_to_text(struct mta_connector *);
116 
117 SPLAY_HEAD(mta_route_tree, mta_route);
118 static struct mta_route *mta_route(struct mta_source *, struct mta_host *);
119 static void mta_route_ref(struct mta_route *);
120 static void mta_route_unref(struct mta_route *);
121 static const char *mta_route_to_text(struct mta_route *);
122 static int mta_route_cmp(const struct mta_route *, const struct mta_route *);
123 SPLAY_PROTOTYPE(mta_route_tree, mta_route, entry, mta_route_cmp);
124 
125 struct mta_block {
126 	SPLAY_ENTRY(mta_block)	 entry;
127 	struct mta_source	*source;
128 	char			*domain;
129 };
130 
131 SPLAY_HEAD(mta_block_tree, mta_block);
132 void mta_block(struct mta_source *, char *);
133 void mta_unblock(struct mta_source *, char *);
134 int mta_is_blocked(struct mta_source *, char *);
135 static int mta_block_cmp(const struct mta_block *, const struct mta_block *);
136 SPLAY_PROTOTYPE(mta_block_tree, mta_block, entry, mta_block_cmp);
137 
138 static struct mta_relay_tree		relays;
139 static struct mta_domain_tree		domains;
140 static struct mta_host_tree		hosts;
141 static struct mta_source_tree		sources;
142 static struct mta_route_tree		routes;
143 static struct mta_block_tree		blocks;
144 
145 static struct tree wait_mx;
146 static struct tree wait_preference;
147 static struct tree wait_secret;
148 static struct tree wait_source;
149 static struct tree flush_evp;
150 static struct event ev_flush_evp;
151 
152 static struct runq *runq_relay;
153 static struct runq *runq_connector;
154 static struct runq *runq_route;
155 static struct runq *runq_hoststat;
156 
157 static time_t	max_seen_conndelay_route;
158 static time_t	max_seen_discdelay_route;
159 
160 #define	HOSTSTAT_EXPIRE_DELAY	(4 * 3600)
161 struct hoststat {
162 	char			 name[HOST_NAME_MAX+1];
163 	time_t			 tm;
164 	char			 error[LINE_MAX];
165 	struct tree		 deferred;
166 };
167 static struct dict hoststat;
168 
169 void mta_hoststat_update(const char *, const char *);
170 void mta_hoststat_cache(const char *, uint64_t);
171 void mta_hoststat_uncache(const char *, uint64_t);
172 void mta_hoststat_reschedule(const char *);
173 static void mta_hoststat_remove_entry(struct hoststat *);
174 
175 
176 void
177 mta_imsg(struct mproc *p, struct imsg *imsg)
178 {
179 	struct mta_relay	*relay;
180 	struct mta_task		*task;
181 	struct mta_domain	*domain;
182 	struct mta_host		*host;
183 	struct mta_route	*route;
184 	struct mta_block	*block;
185 	struct mta_mx		*mx, *imx;
186 	struct mta_source	*source;
187 	struct hoststat		*hs;
188 	struct mta_envelope	*e;
189 	struct sockaddr_storage	 ss;
190 	struct envelope		 evp;
191 	struct msg		 m;
192 	const char		*secret;
193 	const char		*hostname;
194 	const char		*dom;
195 	uint64_t		 reqid;
196 	time_t			 t;
197 	char			 buf[LINE_MAX];
198 	int			 dnserror, preference, v, status;
199 	void			*iter;
200 	uint64_t		 u64;
201 
202 	if (p->proc == PROC_QUEUE) {
203 		switch (imsg->hdr.type) {
204 
205 		case IMSG_QUEUE_TRANSFER:
206 			m_msg(&m, imsg);
207 			m_get_envelope(&m, &evp);
208 			m_end(&m);
209 
210 			relay = mta_relay(&evp);
211 			/* ignore if we don't know the limits yet */
212 			if (relay->limits &&
213 			    relay->ntask >= (size_t)relay->limits->task_hiwat) {
214 				if (!(relay->state & RELAY_ONHOLD)) {
215 					log_info("smtp-out: hiwat reached on %s: holding envelopes",
216 					    mta_relay_to_text(relay));
217 					relay->state |= RELAY_ONHOLD;
218 				}
219 			}
220 
221 			/*
222 			 * If the relay has too many pending tasks, tell the
223 			 * scheduler to hold it until further notice
224 			 */
225 			if (relay->state & RELAY_ONHOLD) {
226 				relay->state |= RELAY_HOLDQ;
227 				m_create(p_queue, IMSG_MTA_DELIVERY_HOLD, 0, 0, -1);
228 				m_add_evpid(p_queue, evp.id);
229 				m_add_id(p_queue, relay->id);
230 				m_close(p_queue);
231 				mta_relay_unref(relay); /* from here */
232 				return;
233 			}
234 
235 			task = NULL;
236 			TAILQ_FOREACH(task, &relay->tasks, entry)
237 				if (task->msgid == evpid_to_msgid(evp.id))
238 					break;
239 
240 			if (task == NULL) {
241 				task = xmalloc(sizeof *task, "mta_task");
242 				TAILQ_INIT(&task->envelopes);
243 				task->relay = relay;
244 				relay->ntask += 1;
245 				TAILQ_INSERT_TAIL(&relay->tasks, task, entry);
246 				task->msgid = evpid_to_msgid(evp.id);
247 				if (evp.sender.user[0] || evp.sender.domain[0])
248 					(void)snprintf(buf, sizeof buf, "%s@%s",
249 					    evp.sender.user, evp.sender.domain);
250 				else
251 					buf[0] = '\0';
252 				task->sender = xstrdup(buf, "mta_task:sender");
253 				stat_increment("mta.task", 1);
254 			}
255 
256 			e = xcalloc(1, sizeof *e, "mta_envelope");
257 			e->id = evp.id;
258 			e->creation = evp.creation;
259 			(void)snprintf(buf, sizeof buf, "%s@%s",
260 			    evp.dest.user, evp.dest.domain);
261 			e->dest = xstrdup(buf, "mta_envelope:dest");
262 			(void)snprintf(buf, sizeof buf, "%s@%s",
263 			    evp.rcpt.user, evp.rcpt.domain);
264 			if (strcmp(buf, e->dest))
265 				e->rcpt = xstrdup(buf, "mta_envelope:rcpt");
266 			e->task = task;
267 			if (evp.dsn_orcpt.user[0] && evp.dsn_orcpt.domain[0]) {
268 				(void)snprintf(buf, sizeof buf, "%s@%s",
269 			    	    evp.dsn_orcpt.user, evp.dsn_orcpt.domain);
270 				e->dsn_orcpt = xstrdup(buf,
271 				    "mta_envelope:dsn_orcpt");
272 			}
273 			(void)strlcpy(e->dsn_envid, evp.dsn_envid,
274 			    sizeof e->dsn_envid);
275 			e->dsn_notify = evp.dsn_notify;
276 			e->dsn_ret = evp.dsn_ret;
277 
278 			TAILQ_INSERT_TAIL(&task->envelopes, e, entry);
279 			log_debug("debug: mta: received evp:%016" PRIx64
280 			    " for <%s>", e->id, e->dest);
281 
282 			stat_increment("mta.envelope", 1);
283 
284 			mta_drain(relay);
285 			mta_relay_unref(relay); /* from here */
286 			return;
287 
288 		case IMSG_MTA_OPEN_MESSAGE:
289 			mta_session_imsg(p, imsg);
290 			return;
291 		}
292 	}
293 
294 	if (p->proc == PROC_LKA) {
295 		switch (imsg->hdr.type) {
296 
297 		case IMSG_MTA_LOOKUP_CREDENTIALS:
298 			m_msg(&m, imsg);
299 			m_get_id(&m, &reqid);
300 			m_get_string(&m, &secret);
301 			m_end(&m);
302 			relay = tree_xpop(&wait_secret, reqid);
303 			mta_on_secret(relay, secret[0] ? secret : NULL);
304 			return;
305 
306 		case IMSG_MTA_LOOKUP_SOURCE:
307 			m_msg(&m, imsg);
308 			m_get_id(&m, &reqid);
309 			m_get_int(&m, &status);
310 			if (status == LKA_OK)
311 				m_get_sockaddr(&m, (struct sockaddr*)&ss);
312 			m_end(&m);
313 
314 			relay = tree_xpop(&wait_source, reqid);
315 			mta_on_source(relay, (status == LKA_OK) ?
316 			    mta_source((struct sockaddr *)&ss) : NULL);
317 			return;
318 
319 		case IMSG_MTA_LOOKUP_HELO:
320 			mta_session_imsg(p, imsg);
321 			return;
322 
323 		case IMSG_MTA_DNS_HOST:
324 			m_msg(&m, imsg);
325 			m_get_id(&m, &reqid);
326 			m_get_sockaddr(&m, (struct sockaddr*)&ss);
327 			m_get_int(&m, &preference);
328 			m_end(&m);
329 			domain = tree_xget(&wait_mx, reqid);
330 			mx = xcalloc(1, sizeof *mx, "mta: mx");
331 			mx->host = mta_host((struct sockaddr*)&ss);
332 			mx->preference = preference;
333 			TAILQ_FOREACH(imx, &domain->mxs, entry) {
334 				if (imx->preference > mx->preference) {
335 					TAILQ_INSERT_BEFORE(imx, mx, entry);
336 					return;
337 				}
338 			}
339 			TAILQ_INSERT_TAIL(&domain->mxs, mx, entry);
340 			return;
341 
342 		case IMSG_MTA_DNS_HOST_END:
343 			m_msg(&m, imsg);
344 			m_get_id(&m, &reqid);
345 			m_get_int(&m, &dnserror);
346 			m_end(&m);
347 			domain = tree_xpop(&wait_mx, reqid);
348 			domain->mxstatus = dnserror;
349 			if (domain->mxstatus == DNS_OK) {
350 				log_debug("debug: MXs for domain %s:",
351 				    domain->name);
352 				TAILQ_FOREACH(mx, &domain->mxs, entry)
353 					log_debug("	%s preference %d",
354 					    sa_to_text(mx->host->sa),
355 					    mx->preference);
356 			}
357 			else {
358 				log_debug("debug: Failed MX query for %s:",
359 				    domain->name);
360 			}
361 			domain->lastmxquery = time(NULL);
362 			waitq_run(&domain->mxs, domain);
363 			return;
364 
365 		case IMSG_MTA_DNS_MX_PREFERENCE:
366 			m_msg(&m, imsg);
367 			m_get_id(&m, &reqid);
368 			m_get_int(&m, &dnserror);
369 			if (dnserror == 0)
370 				m_get_int(&m, &preference);
371 			m_end(&m);
372 
373 			relay = tree_xpop(&wait_preference, reqid);
374 			if (dnserror) {
375 				log_warnx("warn: Couldn't find backup "
376 				    "preference for %s: error %d",
377 				    mta_relay_to_text(relay), dnserror);
378 				preference = INT_MAX;
379 			}
380 			mta_on_preference(relay, preference);
381 			return;
382 
383 		case IMSG_MTA_DNS_PTR:
384 			mta_session_imsg(p, imsg);
385 			return;
386 
387 		case IMSG_MTA_TLS_INIT:
388 			mta_session_imsg(p, imsg);
389 			return;
390 
391 		case IMSG_MTA_TLS_VERIFY:
392 			mta_session_imsg(p, imsg);
393 			return;
394 		}
395 	}
396 
397 	if (p->proc == PROC_PARENT) {
398 		switch (imsg->hdr.type) {
399 		case IMSG_CTL_VERBOSE:
400 			m_msg(&m, imsg);
401 			m_get_int(&m, &v);
402 			m_end(&m);
403 			log_verbose(v);
404 			return;
405 
406 		case IMSG_CTL_PROFILE:
407 			m_msg(&m, imsg);
408 			m_get_int(&m, &v);
409 			m_end(&m);
410 			profiling = v;
411 			return;
412 		}
413 	}
414 
415 	if (p->proc == PROC_CONTROL) {
416 		switch (imsg->hdr.type) {
417 
418 		case IMSG_CTL_RESUME_ROUTE:
419 			u64 = *((uint64_t *)imsg->data);
420 			if (u64)
421 				log_debug("resuming route: %llu",
422 				    (unsigned long long)u64);
423 			else
424 				log_debug("resuming all routes");
425 			SPLAY_FOREACH(route, mta_route_tree, &routes) {
426 				if (u64 && route->id != u64)
427 					continue;
428 
429 				if (route->flags & ROUTE_DISABLED) {
430 					log_info("smtp-out: Enabling route %s per admin request",
431 					    mta_route_to_text(route));
432 					if (!runq_cancel(runq_route, NULL, route)) {
433 						log_warnx("warn: route not on runq");
434 						fatalx("exiting");
435 					}
436 					route->flags &= ~ROUTE_DISABLED;
437 					route->flags |= ROUTE_NEW;
438 					route->nerror = 0;
439 					route->penalty = 0;
440 					mta_route_unref(route); /* from mta_route_disable */
441 				}
442 
443 				if (u64)
444 					break;
445 			}
446 			return;
447 
448 		case IMSG_CTL_MTA_SHOW_HOSTS:
449 			t = time(NULL);
450 			SPLAY_FOREACH(host, mta_host_tree, &hosts) {
451 				(void)snprintf(buf, sizeof(buf),
452 				    "%s %s refcount=%d nconn=%zu lastconn=%s",
453 				    sockaddr_to_text(host->sa),
454 				    host->ptrname,
455 				    host->refcount,
456 				    host->nconn,
457 				    host->lastconn ? duration_to_text(t - host->lastconn) : "-");
458 				m_compose(p, IMSG_CTL_MTA_SHOW_HOSTS,
459 				    imsg->hdr.peerid, 0, -1,
460 				    buf, strlen(buf) + 1);
461 			}
462 			m_compose(p, IMSG_CTL_MTA_SHOW_HOSTS, imsg->hdr.peerid,
463 			    0, -1, NULL, 0);
464 			return;
465 
466 		case IMSG_CTL_MTA_SHOW_RELAYS:
467 			t = time(NULL);
468 			SPLAY_FOREACH(relay, mta_relay_tree, &relays)
469 				mta_relay_show(relay, p, imsg->hdr.peerid, t);
470 			m_compose(p, IMSG_CTL_MTA_SHOW_RELAYS, imsg->hdr.peerid,
471 			    0, -1, NULL, 0);
472 			return;
473 
474 		case IMSG_CTL_MTA_SHOW_ROUTES:
475 			SPLAY_FOREACH(route, mta_route_tree, &routes) {
476 				v = runq_pending(runq_route, NULL, route, &t);
477 				(void)snprintf(buf, sizeof(buf),
478 				    "%llu. %s %c%c%c%c nconn=%zu nerror=%d penalty=%d timeout=%s",
479 				    (unsigned long long)route->id,
480 				    mta_route_to_text(route),
481 				    route->flags & ROUTE_NEW ? 'N' : '-',
482 				    route->flags & ROUTE_DISABLED ? 'D' : '-',
483 				    route->flags & ROUTE_RUNQ ? 'Q' : '-',
484 				    route->flags & ROUTE_KEEPALIVE ? 'K' : '-',
485 				    route->nconn,
486 				    route->nerror,
487 				    route->penalty,
488 				    v ? duration_to_text(t - time(NULL)) : "-");
489 				m_compose(p, IMSG_CTL_MTA_SHOW_ROUTES,
490 				    imsg->hdr.peerid, 0, -1,
491 				    buf, strlen(buf) + 1);
492 			}
493 			m_compose(p, IMSG_CTL_MTA_SHOW_ROUTES, imsg->hdr.peerid,
494 			    0, -1, NULL, 0);
495 			return;
496 
497 		case IMSG_CTL_MTA_SHOW_HOSTSTATS:
498 			iter = NULL;
499 			while (dict_iter(&hoststat, &iter, &hostname,
500 				(void **)&hs)) {
501 				(void)snprintf(buf, sizeof(buf),
502 				    "%s|%llu|%s",
503 				    hostname, (unsigned long long) hs->tm,
504 				    hs->error);
505 				m_compose(p, IMSG_CTL_MTA_SHOW_HOSTSTATS,
506 				    imsg->hdr.peerid, 0, -1,
507 				    buf, strlen(buf) + 1);
508 			}
509 			m_compose(p, IMSG_CTL_MTA_SHOW_HOSTSTATS,
510 			    imsg->hdr.peerid,
511 			    0, -1, NULL, 0);
512 			return;
513 
514 		case IMSG_CTL_MTA_BLOCK:
515 			m_msg(&m, imsg);
516 			m_get_sockaddr(&m, (struct sockaddr*)&ss);
517 			m_get_string(&m, &dom);
518 			m_end(&m);
519 			source = mta_source((struct sockaddr*)&ss);
520 			if (*dom != '\0') {
521 				if (!(strlcpy(buf, dom, sizeof(buf))
522 					>= sizeof(buf)))
523 					mta_block(source, buf);
524 			}
525 			else
526 				mta_block(source, NULL);
527 			mta_source_unref(source);
528 			m_compose(p, IMSG_CTL_OK, imsg->hdr.peerid, 0, -1, NULL, 0);
529 			return;
530 
531 		case IMSG_CTL_MTA_UNBLOCK:
532 			m_msg(&m, imsg);
533 			m_get_sockaddr(&m, (struct sockaddr*)&ss);
534 			m_get_string(&m, &dom);
535 			m_end(&m);
536 			source = mta_source((struct sockaddr*)&ss);
537 			if (*dom != '\0') {
538 				if (!(strlcpy(buf, dom, sizeof(buf))
539 					>= sizeof(buf)))
540 					mta_unblock(source, buf);
541 			}
542 			else
543 				mta_unblock(source, NULL);
544 			mta_source_unref(source);
545 			m_compose(p, IMSG_CTL_OK, imsg->hdr.peerid, 0, -1, NULL, 0);
546 			return;
547 
548 		case IMSG_CTL_MTA_SHOW_BLOCK:
549 			SPLAY_FOREACH(block, mta_block_tree, &blocks) {
550 				(void)snprintf(buf, sizeof(buf), "%s -> %s",
551 				    mta_source_to_text(block->source),
552 				    block->domain ? block->domain : "*");
553 				m_compose(p, IMSG_CTL_MTA_SHOW_BLOCK,
554 				    imsg->hdr.peerid, 0, -1, buf, strlen(buf) + 1);
555 			}
556 			m_compose(p, IMSG_CTL_MTA_SHOW_BLOCK, imsg->hdr.peerid,
557 			    0, -1, NULL, 0);
558 			return;
559 		}
560 	}
561 
562 	errx(1, "mta_imsg: unexpected %s imsg", imsg_to_str(imsg->hdr.type));
563 }
564 
565 void
566 mta_postfork(void)
567 {
568 }
569 
570 void
571 mta_postprivdrop(void)
572 {
573 	SPLAY_INIT(&relays);
574 	SPLAY_INIT(&domains);
575 	SPLAY_INIT(&hosts);
576 	SPLAY_INIT(&sources);
577 	SPLAY_INIT(&routes);
578 	SPLAY_INIT(&blocks);
579 
580 	tree_init(&wait_secret);
581 	tree_init(&wait_mx);
582 	tree_init(&wait_preference);
583 	tree_init(&wait_source);
584 	tree_init(&flush_evp);
585 	dict_init(&hoststat);
586 
587 	evtimer_set(&ev_flush_evp, mta_delivery_flush_event, NULL);
588 
589 	runq_init(&runq_relay, mta_on_timeout);
590 	runq_init(&runq_connector, mta_on_timeout);
591 	runq_init(&runq_route, mta_on_timeout);
592 	runq_init(&runq_hoststat, mta_on_timeout);
593 }
594 
595 
596 /*
597  * Local error on the given source.
598  */
599 void
600 mta_source_error(struct mta_relay *relay, struct mta_route *route, const char *e)
601 {
602 	struct mta_connector	*c;
603 
604 	/*
605 	 * Remember the source as broken for this connector.
606 	 */
607 	c = mta_connector(relay, route->src);
608 	if (!(c->flags & CONNECTOR_ERROR_SOURCE))
609 		log_info("smtp-out: Error on %s: %s",
610 		    mta_route_to_text(route), e);
611 	c->flags |= CONNECTOR_ERROR_SOURCE;
612 }
613 
614 void
615 mta_route_error(struct mta_relay *relay, struct mta_route *route)
616 {
617 #if 0
618 	route->nerror += 1;
619 
620 	if (route->nerror > MAXERROR_PER_ROUTE) {
621 		log_info("smtp-out: Too many errors on %s: "
622 		    "disabling for a while", mta_route_to_text(route));
623 		mta_route_disable(route, 2, ROUTE_DISABLED_SMTP);
624 	}
625 #endif
626 }
627 
628 void
629 mta_route_ok(struct mta_relay *relay, struct mta_route *route)
630 {
631 	struct mta_connector	*c;
632 
633 	if (!(route->flags & ROUTE_NEW))
634 		return;
635 
636 	log_debug("debug: mta-routing: route %s is now valid.",
637 	    mta_route_to_text(route));
638 
639 	route->nerror = 0;
640 	route->flags &= ~ROUTE_NEW;
641 
642 	c = mta_connector(relay, route->src);
643 	mta_connect(c);
644 }
645 
646 void
647 mta_route_down(struct mta_relay *relay, struct mta_route *route)
648 {
649 #if 0
650 	mta_route_disable(route, 2, ROUTE_DISABLED_SMTP);
651 #endif
652 }
653 
654 void
655 mta_route_collect(struct mta_relay *relay, struct mta_route *route)
656 {
657 	struct mta_connector	*c;
658 
659 	log_debug("debug: mta_route_collect(%s)",
660 	    mta_route_to_text(route));
661 
662 	relay->nconn -= 1;
663 	relay->domain->nconn -= 1;
664 	route->nconn -= 1;
665 	route->src->nconn -= 1;
666 	route->dst->nconn -= 1;
667 	route->lastdisc = time(NULL);
668 
669 	/* First connection failed */
670 	if (route->flags & ROUTE_NEW)
671 		mta_route_disable(route, 1, ROUTE_DISABLED_NET);
672 
673 	c = mta_connector(relay, route->src);
674 	c->nconn -= 1;
675 	mta_connect(c);
676 	mta_route_unref(route); /* from mta_find_route() */
677 	mta_relay_unref(relay); /* from mta_connect() */
678 }
679 
680 struct mta_task *
681 mta_route_next_task(struct mta_relay *relay, struct mta_route *route)
682 {
683 	struct mta_task	*task;
684 
685 	if ((task = TAILQ_FIRST(&relay->tasks))) {
686 		TAILQ_REMOVE(&relay->tasks, task, entry);
687 		relay->ntask -= 1;
688 		task->relay = NULL;
689 
690 		/* When the number of tasks is down to lowat, query some evp */
691 		if (relay->ntask == (size_t)relay->limits->task_lowat) {
692 			if (relay->state & RELAY_ONHOLD) {
693 				log_info("smtp-out: back to lowat on %s: releasing",
694 				    mta_relay_to_text(relay));
695 				relay->state &= ~RELAY_ONHOLD;
696 			}
697 			if (relay->state & RELAY_HOLDQ) {
698 				m_create(p_queue, IMSG_MTA_HOLDQ_RELEASE, 0, 0, -1);
699 				m_add_id(p_queue, relay->id);
700 				m_add_int(p_queue, relay->limits->task_release);
701 				m_close(p_queue);
702 			}
703 		}
704 		else if (relay->ntask == 0 && relay->state & RELAY_HOLDQ) {
705 			m_create(p_queue, IMSG_MTA_HOLDQ_RELEASE, 0, 0, -1);
706 			m_add_id(p_queue, relay->id);
707 			m_add_int(p_queue, 0);
708 			m_close(p_queue);
709 		}
710 	}
711 
712 	return (task);
713 }
714 
715 static void
716 mta_delivery_flush_event(int fd, short event, void *arg)
717 {
718 	struct mta_envelope	*e;
719 	struct timeval		 tv;
720 
721 	if (tree_poproot(&flush_evp, NULL, (void**)(&e))) {
722 
723 		if (e->delivery == IMSG_MTA_DELIVERY_OK) {
724 			m_create(p_queue, IMSG_MTA_DELIVERY_OK, 0, 0, -1);
725 			m_add_evpid(p_queue, e->id);
726 			m_add_int(p_queue, e->ext);
727 			m_close(p_queue);
728 		} else if (e->delivery == IMSG_MTA_DELIVERY_TEMPFAIL) {
729 			m_create(p_queue, IMSG_MTA_DELIVERY_TEMPFAIL, 0, 0, -1);
730 			m_add_evpid(p_queue, e->id);
731 			m_add_string(p_queue, e->status);
732 			m_add_int(p_queue, ESC_OTHER_STATUS);
733 			m_close(p_queue);
734 		}
735 		else if (e->delivery == IMSG_MTA_DELIVERY_PERMFAIL) {
736 			m_create(p_queue, IMSG_MTA_DELIVERY_PERMFAIL, 0, 0, -1);
737 			m_add_evpid(p_queue, e->id);
738 			m_add_string(p_queue, e->status);
739 			m_add_int(p_queue, ESC_OTHER_STATUS);
740 			m_close(p_queue);
741 		}
742 		else if (e->delivery == IMSG_MTA_DELIVERY_LOOP) {
743 			m_create(p_queue, IMSG_MTA_DELIVERY_LOOP, 0, 0, -1);
744 			m_add_evpid(p_queue, e->id);
745 			m_close(p_queue);
746 		}
747 		else {
748 			log_warnx("warn: bad delivery type %d for %016" PRIx64,
749 			    e->delivery, e->id);
750 			fatalx("aborting");
751 		}
752 
753 		log_debug("debug: mta: flush for %016"PRIx64" (-> %s)", e->id, e->dest);
754 
755 		free(e->dest);
756 		free(e->rcpt);
757 		free(e->dsn_orcpt);
758 		free(e);
759 
760 		tv.tv_sec = 0;
761 		tv.tv_usec = 0;
762 		evtimer_add(&ev_flush_evp, &tv);
763 	}
764 }
765 
766 void
767 mta_delivery_log(struct mta_envelope *e, const char *source, const char *relay,
768     int delivery, const char *status)
769 {
770 	if (delivery == IMSG_MTA_DELIVERY_OK)
771 		mta_log(e, "Ok", source, relay, status);
772 	else if (delivery == IMSG_MTA_DELIVERY_TEMPFAIL)
773 		mta_log(e, "TempFail", source, relay, status);
774 	else if (delivery == IMSG_MTA_DELIVERY_PERMFAIL)
775 		mta_log(e, "PermFail", source, relay, status);
776 	else if (delivery == IMSG_MTA_DELIVERY_LOOP)
777 		mta_log(e, "PermFail", source, relay, "Loop detected");
778 	else {
779 		log_warnx("warn: bad delivery type %d for %016" PRIx64,
780 		    delivery, e->id);
781 		fatalx("aborting");
782 	}
783 
784 	e->delivery = delivery;
785 	if (status)
786 		(void)strlcpy(e->status, status, sizeof(e->status));
787 }
788 
789 void
790 mta_delivery_notify(struct mta_envelope *e)
791 {
792 	struct timeval	tv;
793 
794 	tree_xset(&flush_evp, e->id, e);
795 	if (tree_count(&flush_evp) == 1) {
796 		tv.tv_sec = 0;
797 		tv.tv_usec = 0;
798 		evtimer_add(&ev_flush_evp, &tv);
799 	}
800 }
801 
802 static void
803 mta_query_mx(struct mta_relay *relay)
804 {
805 	uint64_t	id;
806 
807 	if (relay->status & RELAY_WAIT_MX)
808 		return;
809 
810 	log_debug("debug: mta: querying MX for %s...",
811 	    mta_relay_to_text(relay));
812 
813 	if (waitq_wait(&relay->domain->mxs, mta_on_mx, relay)) {
814 		id = generate_uid();
815 		tree_xset(&wait_mx, id, relay->domain);
816 		if (relay->domain->flags)
817 			m_create(p_lka,  IMSG_MTA_DNS_HOST, 0, 0, -1);
818 		else
819 			m_create(p_lka,  IMSG_MTA_DNS_MX, 0, 0, -1);
820 		m_add_id(p_lka, id);
821 		m_add_string(p_lka, relay->domain->name);
822 		m_close(p_lka);
823 	}
824 	relay->status |= RELAY_WAIT_MX;
825 	mta_relay_ref(relay);
826 }
827 
828 static void
829 mta_query_limits(struct mta_relay *relay)
830 {
831 	if (relay->status & RELAY_WAIT_LIMITS)
832 		return;
833 
834 	relay->limits = dict_get(env->sc_limits_dict, relay->domain->name);
835 	if (relay->limits == NULL)
836 		relay->limits = dict_get(env->sc_limits_dict, "default");
837 
838 	if (max_seen_conndelay_route < relay->limits->conndelay_route)
839 		max_seen_conndelay_route = relay->limits->conndelay_route;
840 	if (max_seen_discdelay_route < relay->limits->discdelay_route)
841 		max_seen_discdelay_route = relay->limits->discdelay_route;
842 }
843 
844 static void
845 mta_query_secret(struct mta_relay *relay)
846 {
847 	if (relay->status & RELAY_WAIT_SECRET)
848 		return;
849 
850 	log_debug("debug: mta: querying secret for %s...",
851 	    mta_relay_to_text(relay));
852 
853 	tree_xset(&wait_secret, relay->id, relay);
854 	relay->status |= RELAY_WAIT_SECRET;
855 
856 	m_create(p_lka, IMSG_MTA_LOOKUP_CREDENTIALS, 0, 0, -1);
857 	m_add_id(p_lka, relay->id);
858 	m_add_string(p_lka, relay->authtable);
859 	m_add_string(p_lka, relay->authlabel);
860 	m_close(p_lka);
861 
862 	mta_relay_ref(relay);
863 }
864 
865 static void
866 mta_query_preference(struct mta_relay *relay)
867 {
868 	if (relay->status & RELAY_WAIT_PREFERENCE)
869 		return;
870 
871 	log_debug("debug: mta: querying preference for %s...",
872 	    mta_relay_to_text(relay));
873 
874 	tree_xset(&wait_preference, relay->id, relay);
875 	relay->status |= RELAY_WAIT_PREFERENCE;
876 
877 	m_create(p_lka,  IMSG_MTA_DNS_MX_PREFERENCE, 0, 0, -1);
878 	m_add_id(p_lka, relay->id);
879 	m_add_string(p_lka, relay->domain->name);
880 	m_add_string(p_lka, relay->backupname);
881 	m_close(p_lka);
882 
883 	mta_relay_ref(relay);
884 }
885 
886 static void
887 mta_query_source(struct mta_relay *relay)
888 {
889 	log_debug("debug: mta: querying source for %s...",
890 	    mta_relay_to_text(relay));
891 
892 	relay->sourceloop += 1;
893 
894 	if (relay->sourcetable == NULL) {
895 		/*
896 		 * This is a recursive call, but it only happens once, since
897 		 * another source will not be queried immediately.
898 		 */
899 		mta_relay_ref(relay);
900 		mta_on_source(relay, mta_source(NULL));
901 		return;
902 	}
903 
904 	m_create(p_lka, IMSG_MTA_LOOKUP_SOURCE, 0, 0, -1);
905 	m_add_id(p_lka, relay->id);
906 	m_add_string(p_lka, relay->sourcetable);
907 	m_close(p_lka);
908 
909 	tree_xset(&wait_source, relay->id, relay);
910 	relay->status |= RELAY_WAIT_SOURCE;
911 	mta_relay_ref(relay);
912 }
913 
914 static void
915 mta_on_mx(void *tag, void *arg, void *data)
916 {
917 	struct mta_domain	*domain = data;
918 	struct mta_relay	*relay = arg;
919 
920 	log_debug("debug: mta: ... got mx (%p, %s, %s)",
921 	    tag, domain->name, mta_relay_to_text(relay));
922 
923 	switch (domain->mxstatus) {
924 	case DNS_OK:
925 		break;
926 	case DNS_RETRY:
927 		relay->fail = IMSG_MTA_DELIVERY_TEMPFAIL;
928 		relay->failstr = "Temporary failure in MX lookup";
929 		break;
930 	case DNS_EINVAL:
931 		relay->fail = IMSG_MTA_DELIVERY_PERMFAIL;
932 		relay->failstr = "Invalid domain name";
933 		break;
934 	case DNS_ENONAME:
935 		relay->fail = IMSG_MTA_DELIVERY_PERMFAIL;
936 		relay->failstr = "Domain does not exist";
937 		break;
938 	case DNS_ENOTFOUND:
939 		relay->fail = IMSG_MTA_DELIVERY_TEMPFAIL;
940 		relay->failstr = "No MX found for domain";
941 		break;
942 	default:
943 		fatalx("bad DNS lookup error code");
944 		break;
945 	}
946 
947 	if (domain->mxstatus)
948 		log_info("smtp-out: Failed to resolve MX for %s: %s",
949 		    mta_relay_to_text(relay), relay->failstr);
950 
951 	relay->status &= ~RELAY_WAIT_MX;
952 	mta_drain(relay);
953 	mta_relay_unref(relay); /* from mta_drain() */
954 }
955 
956 static void
957 mta_on_secret(struct mta_relay *relay, const char *secret)
958 {
959 	log_debug("debug: mta: ... got secret for %s: %s",
960 	    mta_relay_to_text(relay), secret);
961 
962 	if (secret)
963 		relay->secret = strdup(secret);
964 
965 	if (relay->secret == NULL) {
966 		log_warnx("warn: Failed to retrieve secret "
967 			    "for %s", mta_relay_to_text(relay));
968 		relay->fail = IMSG_MTA_DELIVERY_TEMPFAIL;
969 		relay->failstr = "Could not retrieve credentials";
970 	}
971 
972 	relay->status &= ~RELAY_WAIT_SECRET;
973 	mta_drain(relay);
974 	mta_relay_unref(relay); /* from mta_query_secret() */
975 }
976 
977 static void
978 mta_on_preference(struct mta_relay *relay, int preference)
979 {
980 	log_debug("debug: mta: ... got preference for %s: %d",
981 	    mta_relay_to_text(relay), preference);
982 
983 	relay->backuppref = preference;
984 
985 	relay->status &= ~RELAY_WAIT_PREFERENCE;
986 	mta_drain(relay);
987 	mta_relay_unref(relay); /* from mta_query_preference() */
988 }
989 
990 static void
991 mta_on_source(struct mta_relay *relay, struct mta_source *source)
992 {
993 	struct mta_connector	*c;
994 	void			*iter;
995 	int			 delay, errmask;
996 
997 	log_debug("debug: mta: ... got source for %s: %s",
998 	    mta_relay_to_text(relay), source ? mta_source_to_text(source) : "NULL");
999 
1000 	relay->lastsource = time(NULL);
1001 	delay = DELAY_CHECK_SOURCE_SLOW;
1002 
1003 	if (source) {
1004 		c = mta_connector(relay, source);
1005 		if (c->flags & CONNECTOR_NEW) {
1006 			c->flags &= ~CONNECTOR_NEW;
1007 			delay = DELAY_CHECK_SOURCE;
1008 		}
1009 		mta_connect(c);
1010 		if ((c->flags & CONNECTOR_ERROR) == 0)
1011 			relay->sourceloop = 0;
1012 		else
1013 			delay = DELAY_CHECK_SOURCE_FAST;
1014 		mta_source_unref(source); /* from constructor */
1015 	}
1016 	else {
1017 		log_warnx("warn: Failed to get source address for %s",
1018 		    mta_relay_to_text(relay));
1019 	}
1020 
1021 	if (tree_count(&relay->connectors) == 0) {
1022 		relay->fail = IMSG_MTA_DELIVERY_TEMPFAIL;
1023 		relay->failstr = "Could not retrieve source address";
1024 	}
1025 	if (tree_count(&relay->connectors) < relay->sourceloop) {
1026 		relay->fail = IMSG_MTA_DELIVERY_TEMPFAIL;
1027 		relay->failstr = "No valid route to remote MX";
1028 
1029 		errmask = 0;
1030 		iter = NULL;
1031 		while (tree_iter(&relay->connectors, &iter, NULL, (void **)&c))
1032 			errmask |= c->flags;
1033 
1034 		if (errmask & CONNECTOR_ERROR_ROUTE_SMTP)
1035 			relay->failstr = "Destination seem to reject all mails";
1036 		else if (errmask & CONNECTOR_ERROR_ROUTE_NET)
1037 			relay->failstr = "Network error on destination MXs";
1038 		else if (errmask & CONNECTOR_ERROR_MX)
1039 			relay->failstr = "No MX found for destination";
1040 		else if (errmask & CONNECTOR_ERROR_FAMILY)
1041 			relay->failstr = "Address family mismatch on destination MXs";
1042 		else if (errmask & CONNECTOR_ERROR_BLOCKED)
1043 			relay->failstr = "All routes to destination blocked";
1044 		else
1045 			relay->failstr = "No valid route to destination";
1046 	}
1047 
1048 	relay->nextsource = relay->lastsource + delay;
1049 	relay->status &= ~RELAY_WAIT_SOURCE;
1050 	mta_drain(relay);
1051 	mta_relay_unref(relay); /* from mta_query_source() */
1052 }
1053 
1054 static void
1055 mta_connect(struct mta_connector *c)
1056 {
1057 	struct mta_route	*route;
1058 	struct mta_limits	*l = c->relay->limits;
1059 	int			 limits;
1060 	time_t			 nextconn, now;
1061 
1062 	/* toggle the block flag */
1063 	if (mta_is_blocked(c->source, c->relay->domain->name))
1064 		c->flags |= CONNECTOR_ERROR_BLOCKED;
1065 	else
1066 		c->flags &= ~CONNECTOR_ERROR_BLOCKED;
1067 
1068     again:
1069 
1070 	log_debug("debug: mta: connecting with %s", mta_connector_to_text(c));
1071 
1072 	/* Do not connect if this connector has an error. */
1073 	if (c->flags & CONNECTOR_ERROR) {
1074 		log_debug("debug: mta: connector error");
1075 		return;
1076 	}
1077 
1078 	if (c->flags & CONNECTOR_WAIT) {
1079 		log_debug("debug: mta: cancelling connector timeout");
1080 		runq_cancel(runq_connector, NULL, c);
1081 		c->flags &= ~CONNECTOR_WAIT;
1082 	}
1083 
1084 	/* No job. */
1085 	if (c->relay->ntask == 0) {
1086 		log_debug("debug: mta: no task for connector");
1087 		return;
1088 	}
1089 
1090 	/* Do not create more connections than necessary */
1091 	if ((c->relay->nconn_ready >= c->relay->ntask) ||
1092 	    (c->relay->nconn > 2 && c->relay->nconn >= c->relay->ntask / 2)) {
1093 		log_debug("debug: mta: enough connections already");
1094 		return;
1095 	}
1096 
1097 	limits = 0;
1098 	nextconn = now = time(NULL);
1099 
1100 	if (c->relay->domain->lastconn + l->conndelay_domain > nextconn) {
1101 		log_debug("debug: mta: cannot use domain %s before %llus",
1102 		    c->relay->domain->name,
1103 		    (unsigned long long) c->relay->domain->lastconn + l->conndelay_domain - now);
1104 		nextconn = c->relay->domain->lastconn + l->conndelay_domain;
1105 	}
1106 	if (c->relay->domain->nconn >= l->maxconn_per_domain) {
1107 		log_debug("debug: mta: hit domain limit");
1108 		limits |= CONNECTOR_LIMIT_DOMAIN;
1109 	}
1110 
1111 	if (c->source->lastconn + l->conndelay_source > nextconn) {
1112 		log_debug("debug: mta: cannot use source %s before %llus",
1113 		    mta_source_to_text(c->source),
1114 		    (unsigned long long) c->source->lastconn + l->conndelay_source - now);
1115 		nextconn = c->source->lastconn + l->conndelay_source;
1116 	}
1117 	if (c->source->nconn >= l->maxconn_per_source) {
1118 		log_debug("debug: mta: hit source limit");
1119 		limits |= CONNECTOR_LIMIT_SOURCE;
1120 	}
1121 
1122 	if (c->lastconn + l->conndelay_connector > nextconn) {
1123 		log_debug("debug: mta: cannot use %s before %llus",
1124 		    mta_connector_to_text(c),
1125 		    (unsigned long long) c->lastconn + l->conndelay_connector - now);
1126 		nextconn = c->lastconn + l->conndelay_connector;
1127 	}
1128 	if (c->nconn >= l->maxconn_per_connector) {
1129 		log_debug("debug: mta: hit connector limit");
1130 		limits |= CONNECTOR_LIMIT_CONN;
1131 	}
1132 
1133 	if (c->relay->lastconn + l->conndelay_relay > nextconn) {
1134 		log_debug("debug: mta: cannot use %s before %llus",
1135 		    mta_relay_to_text(c->relay),
1136 		    (unsigned long long) c->relay->lastconn + l->conndelay_relay - now);
1137 		nextconn = c->relay->lastconn + l->conndelay_relay;
1138 	}
1139 	if (c->relay->nconn >= l->maxconn_per_relay) {
1140 		log_debug("debug: mta: hit relay limit");
1141 		limits |= CONNECTOR_LIMIT_RELAY;
1142 	}
1143 
1144 	/* We can connect now, find a route */
1145 	if (!limits && nextconn <= now)
1146 		route = mta_find_route(c, now, &limits, &nextconn);
1147 	else
1148 		route = NULL;
1149 
1150 	/* No route */
1151 	if (route == NULL) {
1152 
1153 		if (c->flags & CONNECTOR_ERROR) {
1154 			/* XXX we might want to clear this flag later */
1155 			log_debug("debug: mta-routing: no route available for %s: errors on connector",
1156 			    mta_connector_to_text(c));
1157 			return;
1158 		}
1159 		else if (limits) {
1160 			log_debug("debug: mta-routing: no route available for %s: limits reached",
1161 			    mta_connector_to_text(c));
1162 			nextconn = now + DELAY_CHECK_LIMIT;
1163 		}
1164 		else {
1165 			log_debug("debug: mta-routing: no route available for %s: must wait a bit",
1166 			    mta_connector_to_text(c));
1167 		}
1168 		log_debug("debug: mta: retrying to connect on %s in %llus...",
1169 		    mta_connector_to_text(c),
1170 		    (unsigned long long) nextconn - time(NULL));
1171 		c->flags |= CONNECTOR_WAIT;
1172 		runq_schedule(runq_connector, nextconn, NULL, c);
1173 		return;
1174 	}
1175 
1176 	log_debug("debug: mta-routing: spawning new connection on %s",
1177 		    mta_route_to_text(route));
1178 
1179 	c->nconn += 1;
1180 	c->lastconn = time(NULL);
1181 
1182 	c->relay->nconn += 1;
1183 	c->relay->lastconn = c->lastconn;
1184 	c->relay->domain->nconn += 1;
1185 	c->relay->domain->lastconn = c->lastconn;
1186 	route->nconn += 1;
1187 	route->lastconn = c->lastconn;
1188 	route->src->nconn += 1;
1189 	route->src->lastconn = c->lastconn;
1190 	route->dst->nconn += 1;
1191 	route->dst->lastconn = c->lastconn;
1192 
1193 	mta_session(c->relay, route);	/* this never fails synchronously */
1194 	mta_relay_ref(c->relay);
1195 
1196     goto again;
1197 }
1198 
1199 static void
1200 mta_on_timeout(struct runq *runq, void *arg)
1201 {
1202 	struct mta_connector	*connector = arg;
1203 	struct mta_relay	*relay = arg;
1204 	struct mta_route	*route = arg;
1205 	struct hoststat		*hs = arg;
1206 
1207 	if (runq == runq_relay) {
1208 		log_debug("debug: mta: ... timeout for %s",
1209 		    mta_relay_to_text(relay));
1210 		relay->status &= ~RELAY_WAIT_CONNECTOR;
1211 		mta_drain(relay);
1212 		mta_relay_unref(relay); /* from mta_drain() */
1213 	}
1214 	else if (runq == runq_connector) {
1215 		log_debug("debug: mta: ... timeout for %s",
1216 		    mta_connector_to_text(connector));
1217 		connector->flags &= ~CONNECTOR_WAIT;
1218 		mta_connect(connector);
1219 	}
1220 	else if (runq == runq_route) {
1221 		route->flags &= ~ROUTE_RUNQ;
1222 		mta_route_enable(route);
1223 		mta_route_unref(route);
1224 	}
1225 	else if (runq == runq_hoststat) {
1226 		log_debug("debug: mta: ... timeout for hoststat %s",
1227 			hs->name);
1228 		mta_hoststat_remove_entry(hs);
1229 		free(hs);
1230 	}
1231 }
1232 
1233 static void
1234 mta_route_disable(struct mta_route *route, int penalty, int reason)
1235 {
1236 	unsigned long long	delay;
1237 
1238 	route->penalty += penalty;
1239 	route->lastpenalty = time(NULL);
1240 	delay = (unsigned long long)DELAY_ROUTE_BASE * route->penalty * route->penalty;
1241 	if (delay > DELAY_ROUTE_MAX)
1242 		delay = DELAY_ROUTE_MAX;
1243 #if 0
1244 	delay = 60;
1245 #endif
1246 
1247 	log_info("smtp-out: Disabling route %s for %llus",
1248 	    mta_route_to_text(route), delay);
1249 
1250 	if (route->flags & ROUTE_DISABLED)
1251 		runq_cancel(runq_route, NULL, route);
1252 	else
1253 		mta_route_ref(route);
1254 
1255 	route->flags |= reason & ROUTE_DISABLED;
1256 	runq_schedule(runq_route, time(NULL) + delay, NULL, route);
1257 }
1258 
1259 static void
1260 mta_route_enable(struct mta_route *route)
1261 {
1262 	if (route->flags & ROUTE_DISABLED) {
1263 		log_info("smtp-out: Enabling route %s",
1264 		    mta_route_to_text(route));
1265 		route->flags &= ~ROUTE_DISABLED;
1266 		route->flags |= ROUTE_NEW;
1267 		route->nerror = 0;
1268 	}
1269 
1270 	if (route->penalty) {
1271 #if DELAY_QUADRATIC
1272 		route->penalty -= 1;
1273 		route->lastpenalty = time(NULL);
1274 #else
1275 		route->penalty = 0;
1276 #endif
1277 	}
1278 }
1279 
1280 static void
1281 mta_drain(struct mta_relay *r)
1282 {
1283 	char			 buf[64];
1284 
1285 	log_debug("debug: mta: draining %s "
1286 	    "refcount=%d, ntask=%zu, nconnector=%zu, nconn=%zu",
1287 	    mta_relay_to_text(r),
1288 	    r->refcount, r->ntask, tree_count(&r->connectors), r->nconn);
1289 
1290 	/*
1291 	 * All done.
1292 	 */
1293 	if (r->ntask == 0) {
1294 		log_debug("debug: mta: all done for %s", mta_relay_to_text(r));
1295 		return;
1296 	}
1297 
1298 	/*
1299 	 * If we know that this relay is failing flush the tasks.
1300 	 */
1301 	if (r->fail) {
1302 		mta_flush(r, r->fail, r->failstr);
1303 		return;
1304 	}
1305 
1306 	/* Query secret if needed. */
1307 	if (r->flags & RELAY_AUTH && r->secret == NULL)
1308 		mta_query_secret(r);
1309 
1310 	/* Query our preference if needed. */
1311 	if (r->backupname && r->backuppref == -1)
1312 		mta_query_preference(r);
1313 
1314 	/* Query the domain MXs if needed. */
1315 	if (r->domain->lastmxquery == 0)
1316 		mta_query_mx(r);
1317 
1318 	/* Query the limits if needed. */
1319 	if (r->limits == NULL)
1320 		mta_query_limits(r);
1321 
1322 	/* Wait until we are ready to proceed. */
1323 	if (r->status & RELAY_WAITMASK) {
1324 		buf[0] = '\0';
1325 		if (r->status & RELAY_WAIT_MX)
1326 			(void)strlcat(buf, " MX", sizeof buf);
1327 		if (r->status & RELAY_WAIT_PREFERENCE)
1328 			(void)strlcat(buf, " preference", sizeof buf);
1329 		if (r->status & RELAY_WAIT_SECRET)
1330 			(void)strlcat(buf, " secret", sizeof buf);
1331 		if (r->status & RELAY_WAIT_SOURCE)
1332 			(void)strlcat(buf, " source", sizeof buf);
1333 		if (r->status & RELAY_WAIT_CONNECTOR)
1334 			(void)strlcat(buf, " connector", sizeof buf);
1335 		log_debug("debug: mta: %s waiting for%s",
1336 		    mta_relay_to_text(r), buf);
1337 		return;
1338 	}
1339 
1340 	/*
1341 	 * We have pending task, and it's maybe time too try a new source.
1342 	 */
1343 	if (r->nextsource <= time(NULL))
1344 		mta_query_source(r);
1345 	else {
1346 		log_debug("debug: mta: scheduling relay %s in %llus...",
1347 		    mta_relay_to_text(r),
1348 		    (unsigned long long) r->nextsource - time(NULL));
1349 		runq_schedule(runq_relay, r->nextsource, NULL, r);
1350 		r->status |= RELAY_WAIT_CONNECTOR;
1351 		mta_relay_ref(r);
1352 	}
1353 }
1354 
1355 static void
1356 mta_flush(struct mta_relay *relay, int fail, const char *error)
1357 {
1358 	struct mta_envelope	*e;
1359 	struct mta_task		*task;
1360 	const char     		*domain;
1361 	void			*iter;
1362 	struct mta_connector	*c;
1363 	size_t			 n, r;
1364 
1365 	log_debug("debug: mta_flush(%s, %d, \"%s\")",
1366 	    mta_relay_to_text(relay), fail, error);
1367 
1368 	if (fail != IMSG_MTA_DELIVERY_TEMPFAIL && fail != IMSG_MTA_DELIVERY_PERMFAIL)
1369 		errx(1, "unexpected delivery status %d", fail);
1370 
1371 	n = 0;
1372 	while ((task = TAILQ_FIRST(&relay->tasks))) {
1373 		TAILQ_REMOVE(&relay->tasks, task, entry);
1374 		while ((e = TAILQ_FIRST(&task->envelopes))) {
1375 			TAILQ_REMOVE(&task->envelopes, e, entry);
1376 
1377 			/*
1378 			 * host was suspended, cache envelope id in hoststat tree
1379 			 * so that it can be retried when a delivery succeeds for
1380 			 * that domain.
1381 			 */
1382 			domain = strchr(e->dest, '@');
1383 			if (fail == IMSG_MTA_DELIVERY_TEMPFAIL && domain) {
1384 				r = 0;
1385 				iter = NULL;
1386 				while (tree_iter(&relay->connectors, &iter,
1387 					NULL, (void **)&c)) {
1388 					if (c->flags & CONNECTOR_ERROR_ROUTE)
1389 						r++;
1390 				}
1391 				if (tree_count(&relay->connectors) == r)
1392 					mta_hoststat_cache(domain+1, e->id);
1393 			}
1394 
1395 			mta_delivery_log(e, NULL, relay->domain->name, fail, error);
1396 			mta_delivery_notify(e);
1397 
1398 			n++;
1399 		}
1400 		free(task->sender);
1401 		free(task);
1402 	}
1403 
1404 	stat_decrement("mta.task", relay->ntask);
1405 	stat_decrement("mta.envelope", n);
1406 	relay->ntask = 0;
1407 
1408 	/* release all waiting envelopes for the relay */
1409 	if (relay->state & RELAY_HOLDQ) {
1410 		m_create(p_queue, IMSG_MTA_HOLDQ_RELEASE, 0, 0, -1);
1411 		m_add_id(p_queue, relay->id);
1412 		m_add_int(p_queue, -1);
1413 		m_close(p_queue);
1414 	}
1415 }
1416 
1417 /*
1418  * Find a route to use for this connector
1419  */
1420 static struct mta_route *
1421 mta_find_route(struct mta_connector *c, time_t now, int *limits,
1422     time_t *nextconn)
1423 {
1424 	struct mta_route	*route, *best;
1425 	struct mta_limits	*l = c->relay->limits;
1426 	struct mta_mx		*mx;
1427 	int			 level, limit_host, limit_route;
1428 	int			 family_mismatch, seen, suspended_route;
1429 	time_t			 tm;
1430 
1431 	log_debug("debug: mta-routing: searching new route for %s...",
1432 	    mta_connector_to_text(c));
1433 
1434 	tm = 0;
1435 	limit_host = 0;
1436 	limit_route = 0;
1437 	suspended_route = 0;
1438 	family_mismatch = 0;
1439 	level = -1;
1440 	best = NULL;
1441 	seen = 0;
1442 
1443 	TAILQ_FOREACH(mx, &c->relay->domain->mxs, entry) {
1444 		/*
1445 		 * New preference level
1446 		 */
1447 		if (mx->preference > level) {
1448 #ifndef IGNORE_MX_PREFERENCE
1449 			/*
1450 			 * Use the current best MX if found.
1451 			 */
1452 			if (best)
1453 				break;
1454 
1455 			/*
1456 			 * No candidate found.  There are valid MXs at this
1457 			 * preference level but they reached their limit, or
1458 			 * we can't connect yet.
1459 			 */
1460 			if (limit_host || limit_route || tm)
1461 				break;
1462 
1463 			/*
1464 			 *  If we are a backup MX, do not relay to MXs with
1465 			 *  a greater preference value.
1466 			 */
1467 			if (c->relay->backuppref >= 0 &&
1468 			    mx->preference >= c->relay->backuppref)
1469 				break;
1470 
1471 			/*
1472 			 * Start looking at MXs on this preference level.
1473 			 */
1474 #endif
1475 			level = mx->preference;
1476 		}
1477 
1478 		if (mx->host->flags & HOST_IGNORE)
1479 			continue;
1480 
1481 		/* Found a possibly valid mx */
1482 		seen++;
1483 
1484 		if ((c->source->sa &&
1485 		     c->source->sa->sa_family != mx->host->sa->sa_family) ||
1486 		    (l->family && l->family != mx->host->sa->sa_family)) {
1487 			log_debug("debug: mta-routing: skipping host %s: AF mismatch",
1488 			    mta_host_to_text(mx->host));
1489 			family_mismatch = 1;
1490 			continue;
1491 		}
1492 
1493 		if (mx->host->nconn >= l->maxconn_per_host) {
1494 			log_debug("debug: mta-routing: skipping host %s: too many connections",
1495 			    mta_host_to_text(mx->host));
1496 			limit_host = 1;
1497 			continue;
1498 		}
1499 
1500 		if (mx->host->lastconn + l->conndelay_host > now) {
1501 			log_debug("debug: mta-routing: skipping host %s: cannot use before %llus",
1502 			    mta_host_to_text(mx->host),
1503 			    (unsigned long long) mx->host->lastconn + l->conndelay_host - now);
1504 			if (tm == 0 || mx->host->lastconn + l->conndelay_host < tm)
1505 				tm = mx->host->lastconn + l->conndelay_host;
1506 			continue;
1507 		}
1508 
1509 		route = mta_route(c->source, mx->host);
1510 
1511 		if (route->flags & ROUTE_DISABLED) {
1512 			log_debug("debug: mta-routing: skipping route %s: suspend",
1513 			    mta_route_to_text(route));
1514 			suspended_route |= route->flags & ROUTE_DISABLED;
1515 			mta_route_unref(route); /* from here */
1516 			continue;
1517 		}
1518 
1519 		if (route->nconn && (route->flags & ROUTE_NEW)) {
1520 			log_debug("debug: mta-routing: skipping route %s: not validated yet",
1521 			    mta_route_to_text(route));
1522 			limit_route = 1;
1523 			mta_route_unref(route); /* from here */
1524 			continue;
1525 		}
1526 
1527 		if (route->nconn >= l->maxconn_per_route) {
1528 			log_debug("debug: mta-routing: skipping route %s: too many connections",
1529 			    mta_route_to_text(route));
1530 			limit_route = 1;
1531 			mta_route_unref(route); /* from here */
1532 			continue;
1533 		}
1534 
1535 		if (route->lastconn + l->conndelay_route > now) {
1536 			log_debug("debug: mta-routing: skipping route %s: cannot use before %llus (delay after connect)",
1537 			    mta_route_to_text(route),
1538 			    (unsigned long long) route->lastconn + l->conndelay_route - now);
1539 			if (tm == 0 || route->lastconn + l->conndelay_route < tm)
1540 				tm = route->lastconn + l->conndelay_route;
1541 			mta_route_unref(route); /* from here */
1542 			continue;
1543 		}
1544 
1545 		if (route->lastdisc + l->discdelay_route > now) {
1546 			log_debug("debug: mta-routing: skipping route %s: cannot use before %llus (delay after disconnect)",
1547 			    mta_route_to_text(route),
1548 			    (unsigned long long) route->lastdisc + l->discdelay_route - now);
1549 			if (tm == 0 || route->lastdisc + l->discdelay_route < tm)
1550 				tm = route->lastdisc + l->discdelay_route;
1551 			mta_route_unref(route); /* from here */
1552 			continue;
1553 		}
1554 
1555 		/* Use the route with the lowest number of connections. */
1556 		if (best && route->nconn >= best->nconn) {
1557 			log_debug("debug: mta-routing: skipping route %s: current one is better",
1558 			    mta_route_to_text(route));
1559 			mta_route_unref(route); /* from here */
1560 			continue;
1561 		}
1562 
1563 		if (best)
1564 			mta_route_unref(best); /* from here */
1565 		best = route;
1566 		log_debug("debug: mta-routing: selecting candidate route %s",
1567 		    mta_route_to_text(route));
1568 	}
1569 
1570 	if (best)
1571 		return (best);
1572 
1573 	/* Order is important */
1574 	if (seen == 0) {
1575 		log_info("smtp-out: No MX found for %s",
1576 		    mta_connector_to_text(c));
1577 		c->flags |= CONNECTOR_ERROR_MX;
1578 	}
1579 	else if (limit_route) {
1580 		log_debug("debug: mta: hit route limit");
1581 		*limits |= CONNECTOR_LIMIT_ROUTE;
1582 	}
1583 	else if (limit_host) {
1584 		log_debug("debug: mta: hit host limit");
1585 		*limits |= CONNECTOR_LIMIT_HOST;
1586 	}
1587 	else if (tm) {
1588 		if (tm > *nextconn)
1589 			*nextconn = tm;
1590 	}
1591 	else if (family_mismatch) {
1592 		log_info("smtp-out: Address family mismatch on %s",
1593 		    mta_connector_to_text(c));
1594 		c->flags |= CONNECTOR_ERROR_FAMILY;
1595 	}
1596 	else if (suspended_route) {
1597 		log_info("smtp-out: No valid route for %s",
1598 		    mta_connector_to_text(c));
1599 		if (suspended_route & ROUTE_DISABLED_NET)
1600 			c->flags |= CONNECTOR_ERROR_ROUTE_NET;
1601 		if (suspended_route & ROUTE_DISABLED_SMTP)
1602 			c->flags |= CONNECTOR_ERROR_ROUTE_SMTP;
1603 	}
1604 
1605 	return (NULL);
1606 }
1607 
1608 static void
1609 mta_log(const struct mta_envelope *evp, const char *prefix, const char *source,
1610     const char *relay, const char *status)
1611 {
1612 	log_info("%016"PRIx64" mta event=delivery evpid=%016"PRIx64" "
1613 	    "from=<%s> to=<%s> rcpt=<%s> source=\"%s\" "
1614 	    "relay=\"%s\" delay=%s result=\"%s\" stat=\"%s\"",
1615 	    evp->session,
1616 	    evp->id,
1617 	    evp->task->sender,
1618 	    evp->dest,
1619 	    evp->rcpt ? evp->rcpt : "-",
1620 	    source ? source : "-",
1621 	    relay,
1622 	    duration_to_text(time(NULL) - evp->creation),
1623 	    prefix,
1624 	    status);
1625 }
1626 
1627 static struct mta_relay *
1628 mta_relay(struct envelope *e)
1629 {
1630 	struct mta_relay	 key, *r;
1631 
1632 	memset(&key, 0, sizeof key);
1633 
1634 	if (e->agent.mta.relay.flags & RELAY_BACKUP) {
1635 		key.domain = mta_domain(e->dest.domain, 0);
1636 		key.backupname = e->agent.mta.relay.hostname;
1637 	} else if (e->agent.mta.relay.hostname[0]) {
1638 		key.domain = mta_domain(e->agent.mta.relay.hostname, 1);
1639 		key.flags |= RELAY_MX;
1640 	} else {
1641 		key.domain = mta_domain(e->dest.domain, 0);
1642 		if (!(e->agent.mta.relay.flags & RELAY_STARTTLS))
1643 			key.flags |= RELAY_TLS_OPTIONAL;
1644 	}
1645 
1646 	key.flags |= e->agent.mta.relay.flags;
1647 	key.port = e->agent.mta.relay.port;
1648 	key.pki_name = e->agent.mta.relay.pki_name;
1649 	if (!key.pki_name[0])
1650 		key.pki_name = NULL;
1651 	key.ca_name = e->agent.mta.relay.ca_name;
1652 	if (!key.ca_name[0])
1653 		key.ca_name = NULL;
1654 	key.authtable = e->agent.mta.relay.authtable;
1655 	if (!key.authtable[0])
1656 		key.authtable = NULL;
1657 	key.authlabel = e->agent.mta.relay.authlabel;
1658 	if (!key.authlabel[0])
1659 		key.authlabel = NULL;
1660 	key.sourcetable = e->agent.mta.relay.sourcetable;
1661 	if (!key.sourcetable[0])
1662 		key.sourcetable = NULL;
1663 	key.helotable = e->agent.mta.relay.helotable;
1664 	if (!key.helotable[0])
1665 		key.helotable = NULL;
1666 	key.heloname = e->agent.mta.relay.heloname;
1667 	if (!key.heloname[0])
1668 		key.heloname = NULL;
1669 
1670 	if ((r = SPLAY_FIND(mta_relay_tree, &relays, &key)) == NULL) {
1671 		r = xcalloc(1, sizeof *r, "mta_relay");
1672 		TAILQ_INIT(&r->tasks);
1673 		r->id = generate_uid();
1674 		r->flags = key.flags;
1675 		r->domain = key.domain;
1676 		r->backupname = key.backupname ?
1677 		    xstrdup(key.backupname, "mta: backupname") : NULL;
1678 		r->backuppref = -1;
1679 		r->port = key.port;
1680 		r->pki_name = key.pki_name ? xstrdup(key.pki_name, "mta: pki_name") : NULL;
1681 		r->ca_name = key.ca_name ? xstrdup(key.ca_name, "mta: ca_name") : NULL;
1682 		if (key.authtable)
1683 			r->authtable = xstrdup(key.authtable, "mta: authtable");
1684 		if (key.authlabel)
1685 			r->authlabel = xstrdup(key.authlabel, "mta: authlabel");
1686 		if (key.sourcetable)
1687 			r->sourcetable = xstrdup(key.sourcetable,
1688 			    "mta: sourcetable");
1689 		if (key.helotable)
1690 			r->helotable = xstrdup(key.helotable,
1691 			    "mta: helotable");
1692 		if (key.heloname)
1693 			r->heloname = xstrdup(key.heloname,
1694 			    "mta: heloname");
1695 		SPLAY_INSERT(mta_relay_tree, &relays, r);
1696 		stat_increment("mta.relay", 1);
1697 	} else {
1698 		mta_domain_unref(key.domain); /* from here */
1699 	}
1700 
1701 	r->refcount++;
1702 	return (r);
1703 }
1704 
1705 static void
1706 mta_relay_ref(struct mta_relay *r)
1707 {
1708 	r->refcount++;
1709 }
1710 
1711 static void
1712 mta_relay_unref(struct mta_relay *relay)
1713 {
1714 	struct mta_connector	*c;
1715 
1716 	if (--relay->refcount)
1717 		return;
1718 
1719 	/* Make sure they are no envelopes held for this relay */
1720 	if (relay->state & RELAY_HOLDQ) {
1721 		m_create(p_queue, IMSG_MTA_HOLDQ_RELEASE, 0, 0, -1);
1722 		m_add_id(p_queue, relay->id);
1723 		m_add_int(p_queue, 0);
1724 		m_close(p_queue);
1725 	}
1726 
1727 	log_debug("debug: mta: freeing %s", mta_relay_to_text(relay));
1728 	SPLAY_REMOVE(mta_relay_tree, &relays, relay);
1729 
1730 	while ((tree_poproot(&relay->connectors, NULL, (void**)&c)))
1731 		mta_connector_free(c);
1732 
1733 	free(relay->authlabel);
1734 	free(relay->authtable);
1735 	free(relay->backupname);
1736 	free(relay->pki_name);
1737 	free(relay->ca_name);
1738 	free(relay->helotable);
1739 	free(relay->heloname);
1740 	free(relay->secret);
1741 	free(relay->sourcetable);
1742 
1743 	mta_domain_unref(relay->domain); /* from constructor */
1744 	free(relay);
1745 	stat_decrement("mta.relay", 1);
1746 }
1747 
1748 const char *
1749 mta_relay_to_text(struct mta_relay *relay)
1750 {
1751 	static char	 buf[1024];
1752 	char		 tmp[32];
1753 	const char	*sep = ",";
1754 
1755 	(void)snprintf(buf, sizeof buf, "[relay:%s", relay->domain->name);
1756 
1757 	if (relay->port) {
1758 		(void)strlcat(buf, sep, sizeof buf);
1759 		(void)snprintf(tmp, sizeof tmp, "port=%d", (int)relay->port);
1760 		(void)strlcat(buf, tmp, sizeof buf);
1761 	}
1762 
1763 	if (relay->flags & RELAY_STARTTLS) {
1764 		(void)strlcat(buf, sep, sizeof buf);
1765 		(void)strlcat(buf, "starttls", sizeof buf);
1766 	}
1767 
1768 	if (relay->flags & RELAY_SMTPS) {
1769 		(void)strlcat(buf, sep, sizeof buf);
1770 		(void)strlcat(buf, "smtps", sizeof buf);
1771 	}
1772 
1773 	if (relay->flags & RELAY_AUTH) {
1774 		(void)strlcat(buf, sep, sizeof buf);
1775 		(void)strlcat(buf, "auth=", sizeof buf);
1776 		(void)strlcat(buf, relay->authtable, sizeof buf);
1777 		(void)strlcat(buf, ":", sizeof buf);
1778 		(void)strlcat(buf, relay->authlabel, sizeof buf);
1779 	}
1780 
1781 	if (relay->pki_name) {
1782 		(void)strlcat(buf, sep, sizeof buf);
1783 		(void)strlcat(buf, "pki_name=", sizeof buf);
1784 		(void)strlcat(buf, relay->pki_name, sizeof buf);
1785 	}
1786 
1787 	if (relay->flags & RELAY_MX) {
1788 		(void)strlcat(buf, sep, sizeof buf);
1789 		(void)strlcat(buf, "mx", sizeof buf);
1790 	}
1791 
1792 	if (relay->backupname) {
1793 		(void)strlcat(buf, sep, sizeof buf);
1794 		(void)strlcat(buf, "backup=", sizeof buf);
1795 		(void)strlcat(buf, relay->backupname, sizeof buf);
1796 	}
1797 
1798 	if (relay->sourcetable) {
1799 		(void)strlcat(buf, sep, sizeof buf);
1800 		(void)strlcat(buf, "sourcetable=", sizeof buf);
1801 		(void)strlcat(buf, relay->sourcetable, sizeof buf);
1802 	}
1803 
1804 	if (relay->helotable) {
1805 		(void)strlcat(buf, sep, sizeof buf);
1806 		(void)strlcat(buf, "helotable=", sizeof buf);
1807 		(void)strlcat(buf, relay->helotable, sizeof buf);
1808 	}
1809 
1810 	if (relay->heloname) {
1811 		(void)strlcat(buf, sep, sizeof buf);
1812 		(void)strlcat(buf, "heloname=", sizeof buf);
1813 		(void)strlcat(buf, relay->heloname, sizeof buf);
1814 	}
1815 
1816 	(void)strlcat(buf, "]", sizeof buf);
1817 
1818 	return (buf);
1819 }
1820 
1821 static void
1822 mta_relay_show(struct mta_relay *r, struct mproc *p, uint32_t id, time_t t)
1823 {
1824 	struct mta_connector	*c;
1825 	void			*iter;
1826 	char			 buf[1024], flags[1024], dur[64];
1827 	time_t			 to;
1828 
1829 	flags[0] = '\0';
1830 
1831 #define SHOWSTATUS(f, n) do {							\
1832 		if (r->status & (f)) {						\
1833 			if (flags[0])						\
1834 				(void)strlcat(flags, ",", sizeof(flags));	\
1835 			(void)strlcat(flags, (n), sizeof(flags));		\
1836 		}								\
1837 	} while(0)
1838 
1839 	SHOWSTATUS(RELAY_WAIT_MX, "MX");
1840 	SHOWSTATUS(RELAY_WAIT_PREFERENCE, "preference");
1841 	SHOWSTATUS(RELAY_WAIT_SECRET, "secret");
1842 	SHOWSTATUS(RELAY_WAIT_LIMITS, "limits");
1843 	SHOWSTATUS(RELAY_WAIT_SOURCE, "source");
1844 	SHOWSTATUS(RELAY_WAIT_CONNECTOR, "connector");
1845 #undef SHOWSTATUS
1846 
1847 	if (runq_pending(runq_relay, NULL, r, &to))
1848 		(void)snprintf(dur, sizeof(dur), "%s", duration_to_text(to - t));
1849 	else
1850 		(void)strlcpy(dur, "-", sizeof(dur));
1851 
1852 	(void)snprintf(buf, sizeof(buf), "%s refcount=%d ntask=%zu nconn=%zu lastconn=%s timeout=%s wait=%s%s",
1853 	    mta_relay_to_text(r),
1854 	    r->refcount,
1855 	    r->ntask,
1856 	    r->nconn,
1857 	    r->lastconn ? duration_to_text(t - r->lastconn) : "-",
1858 	    dur,
1859 	    flags,
1860 	    (r->state & RELAY_ONHOLD) ? "ONHOLD" : "");
1861 	m_compose(p, IMSG_CTL_MTA_SHOW_RELAYS, id, 0, -1, buf, strlen(buf) + 1);
1862 
1863 	iter = NULL;
1864 	while (tree_iter(&r->connectors, &iter, NULL, (void **)&c)) {
1865 
1866 		if (runq_pending(runq_connector, NULL, c, &to))
1867 			(void)snprintf(dur, sizeof(dur), "%s", duration_to_text(to - t));
1868 		else
1869 			(void)strlcpy(dur, "-", sizeof(dur));
1870 
1871 		flags[0] = '\0';
1872 
1873 #define SHOWFLAG(f, n) do {							\
1874 		if (c->flags & (f)) {						\
1875 			if (flags[0])						\
1876 				(void)strlcat(flags, ",", sizeof(flags));	\
1877 			(void)strlcat(flags, (n), sizeof(flags));		\
1878 		}								\
1879 	} while(0)
1880 
1881 		SHOWFLAG(CONNECTOR_NEW,		"NEW");
1882 		SHOWFLAG(CONNECTOR_WAIT,	"WAIT");
1883 
1884 		SHOWFLAG(CONNECTOR_ERROR_FAMILY,	"ERROR_FAMILY");
1885 		SHOWFLAG(CONNECTOR_ERROR_SOURCE,	"ERROR_SOURCE");
1886 		SHOWFLAG(CONNECTOR_ERROR_MX,		"ERROR_MX");
1887 		SHOWFLAG(CONNECTOR_ERROR_ROUTE_NET,	"ERROR_ROUTE_NET");
1888 		SHOWFLAG(CONNECTOR_ERROR_ROUTE_SMTP,	"ERROR_ROUTE_SMTP");
1889 		SHOWFLAG(CONNECTOR_ERROR_BLOCKED,	"ERROR_BLOCKED");
1890 
1891 		SHOWFLAG(CONNECTOR_LIMIT_HOST,		"LIMIT_HOST");
1892 		SHOWFLAG(CONNECTOR_LIMIT_ROUTE,		"LIMIT_ROUTE");
1893 		SHOWFLAG(CONNECTOR_LIMIT_SOURCE,	"LIMIT_SOURCE");
1894 		SHOWFLAG(CONNECTOR_LIMIT_RELAY,		"LIMIT_RELAY");
1895 		SHOWFLAG(CONNECTOR_LIMIT_CONN,		"LIMIT_CONN");
1896 		SHOWFLAG(CONNECTOR_LIMIT_DOMAIN,	"LIMIT_DOMAIN");
1897 #undef SHOWFLAG
1898 
1899 		(void)snprintf(buf, sizeof(buf),
1900 		    "  connector %s refcount=%d nconn=%zu lastconn=%s timeout=%s flags=%s",
1901 		    mta_source_to_text(c->source),
1902 		    c->refcount,
1903 		    c->nconn,
1904 		    c->lastconn ? duration_to_text(t - c->lastconn) : "-",
1905 		    dur,
1906 		    flags);
1907 		m_compose(p, IMSG_CTL_MTA_SHOW_RELAYS, id, 0, -1, buf,
1908 		    strlen(buf) + 1);
1909 
1910 
1911 	}
1912 }
1913 
1914 static int
1915 mta_relay_cmp(const struct mta_relay *a, const struct mta_relay *b)
1916 {
1917 	int	r;
1918 
1919 	if (a->domain < b->domain)
1920 		return (-1);
1921 	if (a->domain > b->domain)
1922 		return (1);
1923 
1924 	if (a->flags < b->flags)
1925 		return (-1);
1926 	if (a->flags > b->flags)
1927 		return (1);
1928 
1929 	if (a->port < b->port)
1930 		return (-1);
1931 	if (a->port > b->port)
1932 		return (1);
1933 
1934 	if (a->authtable == NULL && b->authtable)
1935 		return (-1);
1936 	if (a->authtable && b->authtable == NULL)
1937 		return (1);
1938 	if (a->authtable && ((r = strcmp(a->authtable, b->authtable))))
1939 		return (r);
1940 	if (a->authlabel && ((r = strcmp(a->authlabel, b->authlabel))))
1941 		return (r);
1942 	if (a->sourcetable == NULL && b->sourcetable)
1943 		return (-1);
1944 	if (a->sourcetable && b->sourcetable == NULL)
1945 		return (1);
1946 	if (a->sourcetable && ((r = strcmp(a->sourcetable, b->sourcetable))))
1947 		return (r);
1948 	if (a->helotable == NULL && b->helotable)
1949 		return (-1);
1950 	if (a->helotable && b->helotable == NULL)
1951 		return (1);
1952 	if (a->helotable && ((r = strcmp(a->helotable, b->helotable))))
1953 		return (r);
1954 	if (a->heloname == NULL && b->heloname)
1955 		return (-1);
1956 	if (a->heloname && b->heloname == NULL)
1957 		return (1);
1958 	if (a->heloname && ((r = strcmp(a->heloname, b->heloname))))
1959 		return (r);
1960 
1961 	if (a->pki_name == NULL && b->pki_name)
1962 		return (-1);
1963 	if (a->pki_name && b->pki_name == NULL)
1964 		return (1);
1965 	if (a->pki_name && ((r = strcmp(a->pki_name, b->pki_name))))
1966 		return (r);
1967 
1968 	if (a->ca_name == NULL && b->ca_name)
1969 		return (-1);
1970 	if (a->ca_name && b->ca_name == NULL)
1971 		return (1);
1972 	if (a->ca_name && ((r = strcmp(a->ca_name, b->ca_name))))
1973 		return (r);
1974 
1975 	if (a->backupname && ((r = strcmp(a->backupname, b->backupname))))
1976 		return (r);
1977 
1978 	return (0);
1979 }
1980 
1981 SPLAY_GENERATE(mta_relay_tree, mta_relay, entry, mta_relay_cmp);
1982 
1983 static struct mta_host *
1984 mta_host(const struct sockaddr *sa)
1985 {
1986 	struct mta_host		key, *h;
1987 	struct sockaddr_storage	ss;
1988 
1989 	memmove(&ss, sa, sa->sa_len);
1990 	key.sa = (struct sockaddr*)&ss;
1991 	h = SPLAY_FIND(mta_host_tree, &hosts, &key);
1992 
1993 	if (h == NULL) {
1994 		h = xcalloc(1, sizeof(*h), "mta_host");
1995 		h->sa = xmemdup(sa, sa->sa_len, "mta_host");
1996 		SPLAY_INSERT(mta_host_tree, &hosts, h);
1997 		stat_increment("mta.host", 1);
1998 	}
1999 
2000 	h->refcount++;
2001 	return (h);
2002 }
2003 
2004 static void
2005 mta_host_ref(struct mta_host *h)
2006 {
2007 	h->refcount++;
2008 }
2009 
2010 static void
2011 mta_host_unref(struct mta_host *h)
2012 {
2013 	if (--h->refcount)
2014 		return;
2015 
2016 	SPLAY_REMOVE(mta_host_tree, &hosts, h);
2017 	free(h->sa);
2018 	free(h->ptrname);
2019 	free(h);
2020 	stat_decrement("mta.host", 1);
2021 }
2022 
2023 const char *
2024 mta_host_to_text(struct mta_host *h)
2025 {
2026 	static char buf[1024];
2027 
2028 	if (h->ptrname)
2029 		(void)snprintf(buf, sizeof buf, "%s (%s)",
2030 		    sa_to_text(h->sa), h->ptrname);
2031 	else
2032 		(void)snprintf(buf, sizeof buf, "%s", sa_to_text(h->sa));
2033 
2034 	return (buf);
2035 }
2036 
2037 static int
2038 mta_host_cmp(const struct mta_host *a, const struct mta_host *b)
2039 {
2040 	if (a->sa->sa_len < b->sa->sa_len)
2041 		return (-1);
2042 	if (a->sa->sa_len > b->sa->sa_len)
2043 		return (1);
2044 	return (memcmp(a->sa, b->sa, a->sa->sa_len));
2045 }
2046 
2047 SPLAY_GENERATE(mta_host_tree, mta_host, entry, mta_host_cmp);
2048 
2049 static struct mta_domain *
2050 mta_domain(char *name, int flags)
2051 {
2052 	struct mta_domain	key, *d;
2053 
2054 	key.name = name;
2055 	key.flags = flags;
2056 	d = SPLAY_FIND(mta_domain_tree, &domains, &key);
2057 
2058 	if (d == NULL) {
2059 		d = xcalloc(1, sizeof(*d), "mta_domain");
2060 		d->name = xstrdup(name, "mta_domain");
2061 		d->flags = flags;
2062 		TAILQ_INIT(&d->mxs);
2063 		SPLAY_INSERT(mta_domain_tree, &domains, d);
2064 		stat_increment("mta.domain", 1);
2065 	}
2066 
2067 	d->refcount++;
2068 	return (d);
2069 }
2070 
2071 #if 0
2072 static void
2073 mta_domain_ref(struct mta_domain *d)
2074 {
2075 	d->refcount++;
2076 }
2077 #endif
2078 
2079 static void
2080 mta_domain_unref(struct mta_domain *d)
2081 {
2082 	struct mta_mx	*mx;
2083 
2084 	if (--d->refcount)
2085 		return;
2086 
2087 	while ((mx = TAILQ_FIRST(&d->mxs))) {
2088 		TAILQ_REMOVE(&d->mxs, mx, entry);
2089 		mta_host_unref(mx->host); /* from IMSG_DNS_HOST */
2090 		free(mx);
2091 	}
2092 
2093 	SPLAY_REMOVE(mta_domain_tree, &domains, d);
2094 	free(d->name);
2095 	free(d);
2096 	stat_decrement("mta.domain", 1);
2097 }
2098 
2099 static int
2100 mta_domain_cmp(const struct mta_domain *a, const struct mta_domain *b)
2101 {
2102 	if (a->flags < b->flags)
2103 		return (-1);
2104 	if (a->flags > b->flags)
2105 		return (1);
2106 	return (strcasecmp(a->name, b->name));
2107 }
2108 
2109 SPLAY_GENERATE(mta_domain_tree, mta_domain, entry, mta_domain_cmp);
2110 
2111 static struct mta_source *
2112 mta_source(const struct sockaddr *sa)
2113 {
2114 	struct mta_source	key, *s;
2115 	struct sockaddr_storage	ss;
2116 
2117 	if (sa) {
2118 		memmove(&ss, sa, sa->sa_len);
2119 		key.sa = (struct sockaddr*)&ss;
2120 	} else
2121 		key.sa = NULL;
2122 	s = SPLAY_FIND(mta_source_tree, &sources, &key);
2123 
2124 	if (s == NULL) {
2125 		s = xcalloc(1, sizeof(*s), "mta_source");
2126 		if (sa)
2127 			s->sa = xmemdup(sa, sa->sa_len, "mta_source");
2128 		SPLAY_INSERT(mta_source_tree, &sources, s);
2129 		stat_increment("mta.source", 1);
2130 	}
2131 
2132 	s->refcount++;
2133 	return (s);
2134 }
2135 
2136 static void
2137 mta_source_ref(struct mta_source *s)
2138 {
2139 	s->refcount++;
2140 }
2141 
2142 static void
2143 mta_source_unref(struct mta_source *s)
2144 {
2145 	if (--s->refcount)
2146 		return;
2147 
2148 	SPLAY_REMOVE(mta_source_tree, &sources, s);
2149 	free(s->sa);
2150 	free(s);
2151 	stat_decrement("mta.source", 1);
2152 }
2153 
2154 static const char *
2155 mta_source_to_text(struct mta_source *s)
2156 {
2157 	static char buf[1024];
2158 
2159 	if (s->sa == NULL)
2160 		return "[]";
2161 	(void)snprintf(buf, sizeof buf, "%s", sa_to_text(s->sa));
2162 	return (buf);
2163 }
2164 
2165 static int
2166 mta_source_cmp(const struct mta_source *a, const struct mta_source *b)
2167 {
2168 	if (a->sa == NULL)
2169 		return ((b->sa == NULL) ? 0 : -1);
2170 	if (b->sa == NULL)
2171 		return (1);
2172 	if (a->sa->sa_len < b->sa->sa_len)
2173 		return (-1);
2174 	if (a->sa->sa_len > b->sa->sa_len)
2175 		return (1);
2176 	return (memcmp(a->sa, b->sa, a->sa->sa_len));
2177 }
2178 
2179 SPLAY_GENERATE(mta_source_tree, mta_source, entry, mta_source_cmp);
2180 
2181 static struct mta_connector *
2182 mta_connector(struct mta_relay *relay, struct mta_source *source)
2183 {
2184 	struct mta_connector	*c;
2185 
2186 	c = tree_get(&relay->connectors, (uintptr_t)(source));
2187 	if (c == NULL) {
2188 		c = xcalloc(1, sizeof(*c), "mta_connector");
2189 		c->relay = relay;
2190 		c->source = source;
2191 		c->flags |= CONNECTOR_NEW;
2192 		mta_source_ref(source);
2193 		tree_xset(&relay->connectors, (uintptr_t)(source), c);
2194 		stat_increment("mta.connector", 1);
2195 		log_debug("debug: mta: new %s", mta_connector_to_text(c));
2196 	}
2197 
2198 	return (c);
2199 }
2200 
2201 static void
2202 mta_connector_free(struct mta_connector *c)
2203 {
2204 	log_debug("debug: mta: freeing %s",
2205 	    mta_connector_to_text(c));
2206 
2207 	if (c->flags & CONNECTOR_WAIT) {
2208 		log_debug("debug: mta: cancelling timeout for %s",
2209 		    mta_connector_to_text(c));
2210 		runq_cancel(runq_connector, NULL, c);
2211 	}
2212 	mta_source_unref(c->source); /* from constructor */
2213 	free(c);
2214 
2215 	stat_decrement("mta.connector", 1);
2216 }
2217 
2218 static const char *
2219 mta_connector_to_text(struct mta_connector *c)
2220 {
2221 	static char buf[1024];
2222 
2223 	(void)snprintf(buf, sizeof buf, "[connector:%s->%s,0x%x]",
2224 	    mta_source_to_text(c->source),
2225 	    mta_relay_to_text(c->relay),
2226 	    c->flags);
2227 	return (buf);
2228 }
2229 
2230 static struct mta_route *
2231 mta_route(struct mta_source *src, struct mta_host *dst)
2232 {
2233 	struct mta_route	key, *r;
2234 	static uint64_t		rid = 0;
2235 
2236 	key.src = src;
2237 	key.dst = dst;
2238 	r = SPLAY_FIND(mta_route_tree, &routes, &key);
2239 
2240 	if (r == NULL) {
2241 		r = xcalloc(1, sizeof(*r), "mta_route");
2242 		r->src = src;
2243 		r->dst = dst;
2244 		r->flags |= ROUTE_NEW;
2245 		r->id = ++rid;
2246 		SPLAY_INSERT(mta_route_tree, &routes, r);
2247 		mta_source_ref(src);
2248 		mta_host_ref(dst);
2249 		stat_increment("mta.route", 1);
2250 	}
2251 	else if (r->flags & ROUTE_RUNQ) {
2252 		log_debug("debug: mta: mta_route_ref(): cancelling runq for route %s",
2253 		    mta_route_to_text(r));
2254 		r->flags &= ~(ROUTE_RUNQ | ROUTE_KEEPALIVE);
2255 		runq_cancel(runq_route, NULL, r);
2256 		r->refcount--; /* from mta_route_unref() */
2257 	}
2258 
2259 	r->refcount++;
2260 	return (r);
2261 }
2262 
2263 static void
2264 mta_route_ref(struct mta_route *r)
2265 {
2266 	r->refcount++;
2267 }
2268 
2269 static void
2270 mta_route_unref(struct mta_route *r)
2271 {
2272 	time_t	sched, now;
2273 	int	delay;
2274 
2275 	if (--r->refcount)
2276 		return;
2277 
2278 	/*
2279 	 * Nothing references this route, but we might want to keep it alive
2280 	 * for a while.
2281 	 */
2282 	now = time(NULL);
2283 	sched = 0;
2284 
2285 	if (r->penalty) {
2286 #if DELAY_QUADRATIC
2287 		delay = DELAY_ROUTE_BASE * r->penalty * r->penalty;
2288 #else
2289 		delay = 15 * 60;
2290 #endif
2291 		if (delay > DELAY_ROUTE_MAX)
2292 			delay = DELAY_ROUTE_MAX;
2293 		sched = r->lastpenalty + delay;
2294 		log_debug("debug: mta: mta_route_unref(): keeping route %s alive for %llus (penalty %d)",
2295 		    mta_route_to_text(r), (unsigned long long) sched - now, r->penalty);
2296 	} else if (!(r->flags & ROUTE_KEEPALIVE)) {
2297 		if (r->lastconn + max_seen_conndelay_route > now)
2298 			sched = r->lastconn + max_seen_conndelay_route;
2299 		if (r->lastdisc + max_seen_discdelay_route > now &&
2300 		    r->lastdisc + max_seen_discdelay_route < sched)
2301 			sched = r->lastdisc + max_seen_discdelay_route;
2302 
2303 		if (sched > now)
2304 			log_debug("debug: mta: mta_route_unref(): keeping route %s alive for %llus (imposed delay)",
2305 			    mta_route_to_text(r), (unsigned long long) sched - now);
2306 	}
2307 
2308 	if (sched > now) {
2309 		r->flags |= ROUTE_RUNQ;
2310 		runq_schedule(runq_route, sched, NULL, r);
2311 		r->refcount++;
2312 		return;
2313 	}
2314 
2315 	log_debug("debug: mta: mta_route_unref(): really discarding route %s",
2316 	    mta_route_to_text(r));
2317 
2318 	SPLAY_REMOVE(mta_route_tree, &routes, r);
2319 	mta_source_unref(r->src); /* from constructor */
2320 	mta_host_unref(r->dst); /* from constructor */
2321 	free(r);
2322 	stat_decrement("mta.route", 1);
2323 }
2324 
2325 static const char *
2326 mta_route_to_text(struct mta_route *r)
2327 {
2328 	static char	buf[1024];
2329 
2330 	(void)snprintf(buf, sizeof buf, "%s <-> %s",
2331 	    mta_source_to_text(r->src),
2332 	    mta_host_to_text(r->dst));
2333 
2334 	return (buf);
2335 }
2336 
2337 static int
2338 mta_route_cmp(const struct mta_route *a, const struct mta_route *b)
2339 {
2340 	if (a->src < b->src)
2341 		return (-1);
2342 	if (a->src > b->src)
2343 		return (1);
2344 
2345 	if (a->dst < b->dst)
2346 		return (-1);
2347 	if (a->dst > b->dst)
2348 		return (1);
2349 
2350 	return (0);
2351 }
2352 
2353 SPLAY_GENERATE(mta_route_tree, mta_route, entry, mta_route_cmp);
2354 
2355 void
2356 mta_block(struct mta_source *src, char *dom)
2357 {
2358 	struct mta_block key, *b;
2359 
2360 	key.source = src;
2361 	key.domain = dom;
2362 
2363 	b = SPLAY_FIND(mta_block_tree, &blocks, &key);
2364 	if (b != NULL)
2365 		return;
2366 
2367 	b = xcalloc(1, sizeof(*b), "mta_block");
2368 	if (dom)
2369 		b->domain = xstrdup(dom, "mta_block");
2370 	b->source = src;
2371 	mta_source_ref(src);
2372 	SPLAY_INSERT(mta_block_tree, &blocks, b);
2373 }
2374 
2375 void
2376 mta_unblock(struct mta_source *src, char *dom)
2377 {
2378 	struct mta_block key, *b;
2379 
2380 	key.source = src;
2381 	key.domain = dom;
2382 
2383 	b = SPLAY_FIND(mta_block_tree, &blocks, &key);
2384 	if (b == NULL)
2385 		return;
2386 
2387 	SPLAY_REMOVE(mta_block_tree, &blocks, b);
2388 
2389 	mta_source_unref(b->source);
2390 	free(b->domain);
2391 	free(b);
2392 }
2393 
2394 int
2395 mta_is_blocked(struct mta_source *src, char *dom)
2396 {
2397 	struct mta_block key;
2398 
2399 	key.source = src;
2400 	key.domain = dom;
2401 
2402 	if (SPLAY_FIND(mta_block_tree, &blocks, &key))
2403 		return (1);
2404 
2405 	return (0);
2406 }
2407 
2408 static
2409 int
2410 mta_block_cmp(const struct mta_block *a, const struct mta_block *b)
2411 {
2412 	if (a->source < b->source)
2413 		return (-1);
2414 	if (a->source > b->source)
2415 		return (1);
2416 	if (!a->domain && b->domain)
2417 		return (-1);
2418 	if (a->domain && !b->domain)
2419 		return (1);
2420 	if (a->domain == b->domain)
2421 		return (0);
2422 	return (strcasecmp(a->domain, b->domain));
2423 }
2424 
2425 SPLAY_GENERATE(mta_block_tree, mta_block, entry, mta_block_cmp);
2426 
2427 
2428 
2429 /* hoststat errors are not critical, we do best effort */
2430 void
2431 mta_hoststat_update(const char *host, const char *error)
2432 {
2433 	struct hoststat	*hs = NULL;
2434 	char		 buf[HOST_NAME_MAX+1];
2435 	time_t		 tm;
2436 
2437 	if (!lowercase(buf, host, sizeof buf))
2438 		return;
2439 
2440 	tm = time(NULL);
2441 	hs = dict_get(&hoststat, buf);
2442 	if (hs == NULL) {
2443 		if ((hs = calloc(1, sizeof *hs)) == NULL)
2444 			return;
2445 		tree_init(&hs->deferred);
2446 		runq_schedule(runq_hoststat, tm+HOSTSTAT_EXPIRE_DELAY, NULL, hs);
2447 	}
2448 	(void)strlcpy(hs->name, buf, sizeof hs->name);
2449 	(void)strlcpy(hs->error, error, sizeof hs->error);
2450 	hs->tm = time(NULL);
2451 	dict_set(&hoststat, buf, hs);
2452 
2453 	runq_cancel(runq_hoststat, NULL, hs);
2454 	runq_schedule(runq_hoststat, tm+HOSTSTAT_EXPIRE_DELAY, NULL, hs);
2455 }
2456 
2457 void
2458 mta_hoststat_cache(const char *host, uint64_t evpid)
2459 {
2460 	struct hoststat	*hs = NULL;
2461 	char buf[HOST_NAME_MAX+1];
2462 
2463 	if (!lowercase(buf, host, sizeof buf))
2464 		return;
2465 
2466 	hs = dict_get(&hoststat, buf);
2467 	if (hs == NULL)
2468 		return;
2469 
2470 	if (tree_count(&hs->deferred) >= env->sc_mta_max_deferred)
2471 		return;
2472 
2473 	tree_set(&hs->deferred, evpid, NULL);
2474 }
2475 
2476 void
2477 mta_hoststat_uncache(const char *host, uint64_t evpid)
2478 {
2479 	struct hoststat	*hs = NULL;
2480 	char buf[HOST_NAME_MAX+1];
2481 
2482 	if (!lowercase(buf, host, sizeof buf))
2483 		return;
2484 
2485 	hs = dict_get(&hoststat, buf);
2486 	if (hs == NULL)
2487 		return;
2488 
2489 	tree_pop(&hs->deferred, evpid);
2490 }
2491 
2492 void
2493 mta_hoststat_reschedule(const char *host)
2494 {
2495 	struct hoststat	*hs = NULL;
2496 	char		 buf[HOST_NAME_MAX+1];
2497 	uint64_t	 evpid;
2498 
2499 	if (!lowercase(buf, host, sizeof buf))
2500 		return;
2501 
2502 	hs = dict_get(&hoststat, buf);
2503 	if (hs == NULL)
2504 		return;
2505 
2506 	while (tree_poproot(&hs->deferred, &evpid, NULL)) {
2507 		m_compose(p_queue, IMSG_MTA_SCHEDULE, 0, 0, -1,
2508 		    &evpid, sizeof evpid);
2509 	}
2510 }
2511 
2512 static void
2513 mta_hoststat_remove_entry(struct hoststat *hs)
2514 {
2515 	while (tree_poproot(&hs->deferred, NULL, NULL))
2516 		;
2517 	dict_pop(&hoststat, hs->name);
2518 	runq_cancel(runq_hoststat, NULL, hs);
2519 }
2520