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