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