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