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