1 /* $OpenBSD: mta.c,v 1.248 2024/04/23 13:34:51 jsg 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[0] != '\0') 813 e->dsn_orcpt = xstrdup(evp->dsn_orcpt); 814 (void)strlcpy(e->dsn_envid, evp->dsn_envid, 815 sizeof e->dsn_envid); 816 e->dsn_notify = evp->dsn_notify; 817 e->dsn_ret = evp->dsn_ret; 818 819 TAILQ_INSERT_TAIL(&task->envelopes, e, entry); 820 log_debug("debug: mta: received evp:%016" PRIx64 821 " for <%s>", e->id, e->dest); 822 823 stat_increment("mta.envelope", 1); 824 825 mta_drain(relay); 826 mta_relay_unref(relay); /* from here */ 827 } 828 829 static void 830 mta_delivery_flush_event(int fd, short event, void *arg) 831 { 832 struct mta_envelope *e; 833 struct timeval tv; 834 835 if (tree_poproot(&flush_evp, NULL, (void**)(&e))) { 836 837 if (e->delivery == IMSG_MTA_DELIVERY_OK) { 838 m_create(p_queue, IMSG_MTA_DELIVERY_OK, 0, 0, -1); 839 m_add_evpid(p_queue, e->id); 840 m_add_int(p_queue, e->ext); 841 m_close(p_queue); 842 } else if (e->delivery == IMSG_MTA_DELIVERY_TEMPFAIL) { 843 m_create(p_queue, IMSG_MTA_DELIVERY_TEMPFAIL, 0, 0, -1); 844 m_add_evpid(p_queue, e->id); 845 m_add_string(p_queue, e->status); 846 m_add_int(p_queue, ESC_OTHER_STATUS); 847 m_close(p_queue); 848 } 849 else if (e->delivery == IMSG_MTA_DELIVERY_PERMFAIL) { 850 m_create(p_queue, IMSG_MTA_DELIVERY_PERMFAIL, 0, 0, -1); 851 m_add_evpid(p_queue, e->id); 852 m_add_string(p_queue, e->status); 853 m_add_int(p_queue, ESC_OTHER_STATUS); 854 m_close(p_queue); 855 } 856 else if (e->delivery == IMSG_MTA_DELIVERY_LOOP) { 857 m_create(p_queue, IMSG_MTA_DELIVERY_LOOP, 0, 0, -1); 858 m_add_evpid(p_queue, e->id); 859 m_close(p_queue); 860 } 861 else { 862 log_warnx("warn: bad delivery type %d for %016" PRIx64, 863 e->delivery, e->id); 864 fatalx("aborting"); 865 } 866 867 log_debug("debug: mta: flush for %016"PRIx64" (-> %s)", e->id, e->dest); 868 869 free(e->smtpname); 870 free(e->dest); 871 free(e->rcpt); 872 free(e->dsn_orcpt); 873 free(e); 874 875 tv.tv_sec = 0; 876 tv.tv_usec = 0; 877 evtimer_add(&ev_flush_evp, &tv); 878 } 879 } 880 881 void 882 mta_delivery_log(struct mta_envelope *e, const char *source, const char *relay, 883 int delivery, const char *status) 884 { 885 if (delivery == IMSG_MTA_DELIVERY_OK) 886 mta_log(e, "Ok", source, relay, status); 887 else if (delivery == IMSG_MTA_DELIVERY_TEMPFAIL) 888 mta_log(e, "TempFail", source, relay, status); 889 else if (delivery == IMSG_MTA_DELIVERY_PERMFAIL) 890 mta_log(e, "PermFail", source, relay, status); 891 else if (delivery == IMSG_MTA_DELIVERY_LOOP) 892 mta_log(e, "PermFail", source, relay, "Loop detected"); 893 else { 894 log_warnx("warn: bad delivery type %d for %016" PRIx64, 895 delivery, e->id); 896 fatalx("aborting"); 897 } 898 899 e->delivery = delivery; 900 if (status) 901 (void)strlcpy(e->status, status, sizeof(e->status)); 902 } 903 904 void 905 mta_delivery_notify(struct mta_envelope *e) 906 { 907 struct timeval tv; 908 909 tree_xset(&flush_evp, e->id, e); 910 if (tree_count(&flush_evp) == 1) { 911 tv.tv_sec = 0; 912 tv.tv_usec = 0; 913 evtimer_add(&ev_flush_evp, &tv); 914 } 915 } 916 917 static void 918 mta_query_mx(struct mta_relay *relay) 919 { 920 uint64_t id; 921 922 if (relay->status & RELAY_WAIT_MX) 923 return; 924 925 log_debug("debug: mta: querying MX for %s...", 926 mta_relay_to_text(relay)); 927 928 if (waitq_wait(&relay->domain->mxs, mta_on_mx, relay)) { 929 id = generate_uid(); 930 tree_xset(&wait_mx, id, relay->domain); 931 if (relay->domain->as_host) 932 m_create(p_lka, IMSG_MTA_DNS_HOST, 0, 0, -1); 933 else 934 m_create(p_lka, IMSG_MTA_DNS_MX, 0, 0, -1); 935 m_add_id(p_lka, id); 936 m_add_string(p_lka, relay->domain->name); 937 m_close(p_lka); 938 } 939 relay->status |= RELAY_WAIT_MX; 940 mta_relay_ref(relay); 941 } 942 943 static void 944 mta_query_limits(struct mta_relay *relay) 945 { 946 if (relay->status & RELAY_WAIT_LIMITS) 947 return; 948 949 relay->limits = dict_get(env->sc_limits_dict, relay->domain->name); 950 if (relay->limits == NULL) 951 relay->limits = dict_get(env->sc_limits_dict, "default"); 952 953 if (max_seen_conndelay_route < relay->limits->conndelay_route) 954 max_seen_conndelay_route = relay->limits->conndelay_route; 955 if (max_seen_discdelay_route < relay->limits->discdelay_route) 956 max_seen_discdelay_route = relay->limits->discdelay_route; 957 } 958 959 static void 960 mta_query_secret(struct mta_relay *relay) 961 { 962 if (relay->status & RELAY_WAIT_SECRET) 963 return; 964 965 log_debug("debug: mta: querying secret for %s...", 966 mta_relay_to_text(relay)); 967 968 tree_xset(&wait_secret, relay->id, relay); 969 relay->status |= RELAY_WAIT_SECRET; 970 971 m_create(p_lka, IMSG_MTA_LOOKUP_CREDENTIALS, 0, 0, -1); 972 m_add_id(p_lka, relay->id); 973 m_add_string(p_lka, relay->authtable); 974 m_add_string(p_lka, relay->authlabel); 975 m_close(p_lka); 976 977 mta_relay_ref(relay); 978 } 979 980 static void 981 mta_query_smarthost(struct envelope *evp0) 982 { 983 struct dispatcher *dispatcher; 984 struct envelope *evp; 985 986 evp = malloc(sizeof(*evp)); 987 memmove(evp, evp0, sizeof(*evp)); 988 989 dispatcher = dict_xget(env->sc_dispatchers, evp->dispatcher); 990 991 log_debug("debug: mta: querying smarthost for %s:%s...", 992 evp->dispatcher, dispatcher->u.remote.smarthost); 993 994 tree_xset(&wait_smarthost, evp->id, evp); 995 996 m_create(p_lka, IMSG_MTA_LOOKUP_SMARTHOST, 0, 0, -1); 997 m_add_id(p_lka, evp->id); 998 if (dispatcher->u.remote.smarthost_domain) 999 m_add_string(p_lka, evp->dest.domain); 1000 else 1001 m_add_string(p_lka, NULL); 1002 m_add_string(p_lka, dispatcher->u.remote.smarthost); 1003 m_close(p_lka); 1004 1005 log_debug("debug: mta: querying smarthost"); 1006 } 1007 1008 static void 1009 mta_query_preference(struct mta_relay *relay) 1010 { 1011 if (relay->status & RELAY_WAIT_PREFERENCE) 1012 return; 1013 1014 log_debug("debug: mta: querying preference for %s...", 1015 mta_relay_to_text(relay)); 1016 1017 tree_xset(&wait_preference, relay->id, relay); 1018 relay->status |= RELAY_WAIT_PREFERENCE; 1019 1020 m_create(p_lka, IMSG_MTA_DNS_MX_PREFERENCE, 0, 0, -1); 1021 m_add_id(p_lka, relay->id); 1022 m_add_string(p_lka, relay->domain->name); 1023 m_add_string(p_lka, relay->backupname); 1024 m_close(p_lka); 1025 1026 mta_relay_ref(relay); 1027 } 1028 1029 static void 1030 mta_query_source(struct mta_relay *relay) 1031 { 1032 log_debug("debug: mta: querying source for %s...", 1033 mta_relay_to_text(relay)); 1034 1035 relay->sourceloop += 1; 1036 1037 if (relay->sourcetable == NULL) { 1038 /* 1039 * This is a recursive call, but it only happens once, since 1040 * another source will not be queried immediately. 1041 */ 1042 mta_relay_ref(relay); 1043 mta_on_source(relay, mta_source(NULL)); 1044 return; 1045 } 1046 1047 m_create(p_lka, IMSG_MTA_LOOKUP_SOURCE, 0, 0, -1); 1048 m_add_id(p_lka, relay->id); 1049 m_add_string(p_lka, relay->sourcetable); 1050 m_close(p_lka); 1051 1052 tree_xset(&wait_source, relay->id, relay); 1053 relay->status |= RELAY_WAIT_SOURCE; 1054 mta_relay_ref(relay); 1055 } 1056 1057 static void 1058 mta_on_mx(void *tag, void *arg, void *data) 1059 { 1060 struct mta_domain *domain = data; 1061 struct mta_relay *relay = arg; 1062 1063 log_debug("debug: mta: ... got mx (%p, %s, %s)", 1064 tag, domain->name, mta_relay_to_text(relay)); 1065 1066 switch (domain->mxstatus) { 1067 case DNS_OK: 1068 break; 1069 case DNS_RETRY: 1070 relay->fail = IMSG_MTA_DELIVERY_TEMPFAIL; 1071 relay->failstr = "Temporary failure in MX lookup"; 1072 break; 1073 case DNS_EINVAL: 1074 relay->fail = IMSG_MTA_DELIVERY_PERMFAIL; 1075 relay->failstr = "Invalid domain name"; 1076 break; 1077 case DNS_ENONAME: 1078 relay->fail = IMSG_MTA_DELIVERY_PERMFAIL; 1079 relay->failstr = "Domain does not exist"; 1080 break; 1081 case DNS_ENOTFOUND: 1082 relay->fail = IMSG_MTA_DELIVERY_TEMPFAIL; 1083 if (relay->domain->as_host) 1084 relay->failstr = "Host not found"; 1085 else 1086 relay->failstr = "No MX found for domain"; 1087 break; 1088 case DNS_NULLMX: 1089 relay->fail = IMSG_MTA_DELIVERY_PERMFAIL; 1090 relay->failstr = "Domain does not accept mail"; 1091 break; 1092 default: 1093 fatalx("bad DNS lookup error code"); 1094 break; 1095 } 1096 1097 if (domain->mxstatus) 1098 log_info("smtp-out: Failed to resolve MX for %s: %s", 1099 mta_relay_to_text(relay), relay->failstr); 1100 1101 relay->status &= ~RELAY_WAIT_MX; 1102 mta_drain(relay); 1103 mta_relay_unref(relay); /* from mta_drain() */ 1104 } 1105 1106 static void 1107 mta_on_secret(struct mta_relay *relay, const char *secret) 1108 { 1109 log_debug("debug: mta: ... got secret for %s: %s", 1110 mta_relay_to_text(relay), secret); 1111 1112 if (secret) 1113 relay->secret = strdup(secret); 1114 1115 if (relay->secret == NULL) { 1116 log_warnx("warn: Failed to retrieve secret " 1117 "for %s", mta_relay_to_text(relay)); 1118 relay->fail = IMSG_MTA_DELIVERY_TEMPFAIL; 1119 relay->failstr = "Could not retrieve credentials"; 1120 } 1121 1122 relay->status &= ~RELAY_WAIT_SECRET; 1123 mta_drain(relay); 1124 mta_relay_unref(relay); /* from mta_query_secret() */ 1125 } 1126 1127 static void 1128 mta_on_smarthost(struct envelope *evp, const char *smarthost) 1129 { 1130 if (smarthost == NULL) { 1131 log_warnx("warn: Failed to retrieve smarthost " 1132 "for envelope %"PRIx64, evp->id); 1133 m_create(p_queue, IMSG_MTA_DELIVERY_TEMPFAIL, 0, 0, -1); 1134 m_add_evpid(p_queue, evp->id); 1135 m_add_string(p_queue, "Cannot retrieve smarthost"); 1136 m_add_int(p_queue, ESC_OTHER_STATUS); 1137 m_close(p_queue); 1138 return; 1139 } 1140 1141 log_debug("debug: mta: ... got smarthost for %016"PRIx64": %s", 1142 evp->id, smarthost); 1143 mta_handle_envelope(evp, smarthost); 1144 free(evp); 1145 } 1146 1147 static void 1148 mta_on_preference(struct mta_relay *relay, int preference) 1149 { 1150 log_debug("debug: mta: ... got preference for %s: %d", 1151 mta_relay_to_text(relay), preference); 1152 1153 relay->backuppref = preference; 1154 1155 relay->status &= ~RELAY_WAIT_PREFERENCE; 1156 mta_drain(relay); 1157 mta_relay_unref(relay); /* from mta_query_preference() */ 1158 } 1159 1160 static void 1161 mta_on_source(struct mta_relay *relay, struct mta_source *source) 1162 { 1163 struct mta_connector *c; 1164 void *iter; 1165 int delay, errmask; 1166 1167 log_debug("debug: mta: ... got source for %s: %s", 1168 mta_relay_to_text(relay), source ? mta_source_to_text(source) : "NULL"); 1169 1170 relay->lastsource = time(NULL); 1171 delay = DELAY_CHECK_SOURCE_SLOW; 1172 1173 if (source) { 1174 c = mta_connector(relay, source); 1175 if (c->flags & CONNECTOR_NEW) { 1176 c->flags &= ~CONNECTOR_NEW; 1177 delay = DELAY_CHECK_SOURCE; 1178 } 1179 mta_connect(c); 1180 if ((c->flags & CONNECTOR_ERROR) == 0) 1181 relay->sourceloop = 0; 1182 else 1183 delay = DELAY_CHECK_SOURCE_FAST; 1184 mta_source_unref(source); /* from constructor */ 1185 } 1186 else { 1187 log_warnx("warn: Failed to get source address for %s", 1188 mta_relay_to_text(relay)); 1189 } 1190 1191 if (tree_count(&relay->connectors) == 0) { 1192 relay->fail = IMSG_MTA_DELIVERY_TEMPFAIL; 1193 relay->failstr = "Could not retrieve source address"; 1194 } 1195 if (tree_count(&relay->connectors) < relay->sourceloop) { 1196 relay->fail = IMSG_MTA_DELIVERY_TEMPFAIL; 1197 relay->failstr = "No valid route to remote MX"; 1198 1199 errmask = 0; 1200 iter = NULL; 1201 while (tree_iter(&relay->connectors, &iter, NULL, (void **)&c)) 1202 errmask |= c->flags; 1203 1204 if (errmask & CONNECTOR_ERROR_ROUTE_SMTP) 1205 relay->failstr = "Destination seem to reject all mails"; 1206 else if (errmask & CONNECTOR_ERROR_ROUTE_NET) 1207 relay->failstr = "Network error on destination MXs"; 1208 else if (errmask & CONNECTOR_ERROR_MX) 1209 relay->failstr = "No MX found for destination"; 1210 else if (errmask & CONNECTOR_ERROR_FAMILY) 1211 relay->failstr = "Address family mismatch on destination MXs"; 1212 else if (errmask & CONNECTOR_ERROR_BLOCKED) 1213 relay->failstr = "All routes to destination blocked"; 1214 else 1215 relay->failstr = "No valid route to destination"; 1216 } 1217 1218 relay->nextsource = relay->lastsource + delay; 1219 relay->status &= ~RELAY_WAIT_SOURCE; 1220 mta_drain(relay); 1221 mta_relay_unref(relay); /* from mta_query_source() */ 1222 } 1223 1224 static void 1225 mta_connect(struct mta_connector *c) 1226 { 1227 struct mta_route *route; 1228 struct mta_mx *mx; 1229 struct mta_limits *l = c->relay->limits; 1230 int limits; 1231 time_t nextconn, now; 1232 1233 /* toggle the block flag */ 1234 if (mta_is_blocked(c->source, c->relay->domain->name)) 1235 c->flags |= CONNECTOR_ERROR_BLOCKED; 1236 else 1237 c->flags &= ~CONNECTOR_ERROR_BLOCKED; 1238 1239 again: 1240 1241 log_debug("debug: mta: connecting with %s", mta_connector_to_text(c)); 1242 1243 /* Do not connect if this connector has an error. */ 1244 if (c->flags & CONNECTOR_ERROR) { 1245 log_debug("debug: mta: connector error"); 1246 return; 1247 } 1248 1249 if (c->flags & CONNECTOR_WAIT) { 1250 log_debug("debug: mta: cancelling connector timeout"); 1251 runq_cancel(runq_connector, c); 1252 c->flags &= ~CONNECTOR_WAIT; 1253 } 1254 1255 /* No job. */ 1256 if (c->relay->ntask == 0) { 1257 log_debug("debug: mta: no task for connector"); 1258 return; 1259 } 1260 1261 /* Do not create more connections than necessary */ 1262 if ((c->relay->nconn_ready >= c->relay->ntask) || 1263 (c->relay->nconn > 2 && c->relay->nconn >= c->relay->ntask / 2)) { 1264 log_debug("debug: mta: enough connections already"); 1265 return; 1266 } 1267 1268 limits = 0; 1269 nextconn = now = time(NULL); 1270 1271 if (c->relay->domain->lastconn + l->conndelay_domain > nextconn) { 1272 log_debug("debug: mta: cannot use domain %s before %llus", 1273 c->relay->domain->name, 1274 (unsigned long long) c->relay->domain->lastconn + l->conndelay_domain - now); 1275 nextconn = c->relay->domain->lastconn + l->conndelay_domain; 1276 } 1277 if (c->relay->domain->nconn >= l->maxconn_per_domain) { 1278 log_debug("debug: mta: hit domain limit"); 1279 limits |= CONNECTOR_LIMIT_DOMAIN; 1280 } 1281 1282 if (c->source->lastconn + l->conndelay_source > nextconn) { 1283 log_debug("debug: mta: cannot use source %s before %llus", 1284 mta_source_to_text(c->source), 1285 (unsigned long long) c->source->lastconn + l->conndelay_source - now); 1286 nextconn = c->source->lastconn + l->conndelay_source; 1287 } 1288 if (c->source->nconn >= l->maxconn_per_source) { 1289 log_debug("debug: mta: hit source limit"); 1290 limits |= CONNECTOR_LIMIT_SOURCE; 1291 } 1292 1293 if (c->lastconn + l->conndelay_connector > nextconn) { 1294 log_debug("debug: mta: cannot use %s before %llus", 1295 mta_connector_to_text(c), 1296 (unsigned long long) c->lastconn + l->conndelay_connector - now); 1297 nextconn = c->lastconn + l->conndelay_connector; 1298 } 1299 if (c->nconn >= l->maxconn_per_connector) { 1300 log_debug("debug: mta: hit connector limit"); 1301 limits |= CONNECTOR_LIMIT_CONN; 1302 } 1303 1304 if (c->relay->lastconn + l->conndelay_relay > nextconn) { 1305 log_debug("debug: mta: cannot use %s before %llus", 1306 mta_relay_to_text(c->relay), 1307 (unsigned long long) c->relay->lastconn + l->conndelay_relay - now); 1308 nextconn = c->relay->lastconn + l->conndelay_relay; 1309 } 1310 if (c->relay->nconn >= l->maxconn_per_relay) { 1311 log_debug("debug: mta: hit relay limit"); 1312 limits |= CONNECTOR_LIMIT_RELAY; 1313 } 1314 1315 /* We can connect now, find a route */ 1316 if (!limits && nextconn <= now) 1317 route = mta_find_route(c, now, &limits, &nextconn, &mx); 1318 else 1319 route = NULL; 1320 1321 /* No route */ 1322 if (route == NULL) { 1323 1324 if (c->flags & CONNECTOR_ERROR) { 1325 /* XXX we might want to clear this flag later */ 1326 log_debug("debug: mta-routing: no route available for %s: errors on connector", 1327 mta_connector_to_text(c)); 1328 return; 1329 } 1330 else if (limits) { 1331 log_debug("debug: mta-routing: no route available for %s: limits reached", 1332 mta_connector_to_text(c)); 1333 nextconn = now + DELAY_CHECK_LIMIT; 1334 } 1335 else { 1336 log_debug("debug: mta-routing: no route available for %s: must wait a bit", 1337 mta_connector_to_text(c)); 1338 } 1339 log_debug("debug: mta: retrying to connect on %s in %llus...", 1340 mta_connector_to_text(c), 1341 (unsigned long long) nextconn - time(NULL)); 1342 c->flags |= CONNECTOR_WAIT; 1343 runq_schedule_at(runq_connector, nextconn, c); 1344 return; 1345 } 1346 1347 log_debug("debug: mta-routing: spawning new connection on %s", 1348 mta_route_to_text(route)); 1349 1350 c->nconn += 1; 1351 c->lastconn = time(NULL); 1352 1353 c->relay->nconn += 1; 1354 c->relay->lastconn = c->lastconn; 1355 c->relay->domain->nconn += 1; 1356 c->relay->domain->lastconn = c->lastconn; 1357 route->nconn += 1; 1358 route->lastconn = c->lastconn; 1359 route->src->nconn += 1; 1360 route->src->lastconn = c->lastconn; 1361 route->dst->nconn += 1; 1362 route->dst->lastconn = c->lastconn; 1363 1364 mta_session(c->relay, route, mx->mxname); /* this never fails synchronously */ 1365 mta_relay_ref(c->relay); 1366 1367 goto again; 1368 } 1369 1370 static void 1371 mta_on_timeout(struct runq *runq, void *arg) 1372 { 1373 struct mta_connector *connector = arg; 1374 struct mta_relay *relay = arg; 1375 struct mta_route *route = arg; 1376 struct hoststat *hs = arg; 1377 1378 if (runq == runq_relay) { 1379 log_debug("debug: mta: ... timeout for %s", 1380 mta_relay_to_text(relay)); 1381 relay->status &= ~RELAY_WAIT_CONNECTOR; 1382 mta_drain(relay); 1383 mta_relay_unref(relay); /* from mta_drain() */ 1384 } 1385 else if (runq == runq_connector) { 1386 log_debug("debug: mta: ... timeout for %s", 1387 mta_connector_to_text(connector)); 1388 connector->flags &= ~CONNECTOR_WAIT; 1389 mta_connect(connector); 1390 } 1391 else if (runq == runq_route) { 1392 route->flags &= ~ROUTE_RUNQ; 1393 mta_route_enable(route); 1394 mta_route_unref(route); 1395 } 1396 else if (runq == runq_hoststat) { 1397 log_debug("debug: mta: ... timeout for hoststat %s", 1398 hs->name); 1399 mta_hoststat_remove_entry(hs); 1400 free(hs); 1401 } 1402 } 1403 1404 static void 1405 mta_route_disable(struct mta_route *route, int penalty, int reason) 1406 { 1407 unsigned long long delay; 1408 1409 route->penalty += penalty; 1410 route->lastpenalty = time(NULL); 1411 delay = (unsigned long long)DELAY_ROUTE_BASE * route->penalty * route->penalty; 1412 if (delay > DELAY_ROUTE_MAX) 1413 delay = DELAY_ROUTE_MAX; 1414 #if 0 1415 delay = 60; 1416 #endif 1417 1418 log_info("smtp-out: Disabling route %s for %llus", 1419 mta_route_to_text(route), delay); 1420 1421 if (route->flags & ROUTE_DISABLED) 1422 runq_cancel(runq_route, route); 1423 else 1424 mta_route_ref(route); 1425 1426 route->flags |= reason & ROUTE_DISABLED; 1427 runq_schedule(runq_route, delay, route); 1428 } 1429 1430 static void 1431 mta_route_enable(struct mta_route *route) 1432 { 1433 if (route->flags & ROUTE_DISABLED) { 1434 log_info("smtp-out: Enabling route %s", 1435 mta_route_to_text(route)); 1436 route->flags &= ~ROUTE_DISABLED; 1437 route->flags |= ROUTE_NEW; 1438 route->nerror = 0; 1439 } 1440 1441 if (route->penalty) { 1442 #if DELAY_QUADRATIC 1443 route->penalty -= 1; 1444 route->lastpenalty = time(NULL); 1445 #else 1446 route->penalty = 0; 1447 #endif 1448 } 1449 } 1450 1451 static void 1452 mta_drain(struct mta_relay *r) 1453 { 1454 char buf[64]; 1455 1456 log_debug("debug: mta: draining %s " 1457 "refcount=%d, ntask=%zu, nconnector=%zu, nconn=%zu", 1458 mta_relay_to_text(r), 1459 r->refcount, r->ntask, tree_count(&r->connectors), r->nconn); 1460 1461 /* 1462 * All done. 1463 */ 1464 if (r->ntask == 0) { 1465 log_debug("debug: mta: all done for %s", mta_relay_to_text(r)); 1466 return; 1467 } 1468 1469 /* 1470 * If we know that this relay is failing flush the tasks. 1471 */ 1472 if (r->fail) { 1473 mta_flush(r, r->fail, r->failstr); 1474 return; 1475 } 1476 1477 /* Query secret if needed. */ 1478 if (r->flags & RELAY_AUTH && r->secret == NULL) 1479 mta_query_secret(r); 1480 1481 /* Query our preference if needed. */ 1482 if (r->backupname && r->backuppref == -1) 1483 mta_query_preference(r); 1484 1485 /* Query the domain MXs if needed. */ 1486 if (r->domain->lastmxquery == 0) 1487 mta_query_mx(r); 1488 1489 /* Query the limits if needed. */ 1490 if (r->limits == NULL) 1491 mta_query_limits(r); 1492 1493 /* Wait until we are ready to proceed. */ 1494 if (r->status & RELAY_WAITMASK) { 1495 buf[0] = '\0'; 1496 if (r->status & RELAY_WAIT_MX) 1497 (void)strlcat(buf, " MX", sizeof buf); 1498 if (r->status & RELAY_WAIT_PREFERENCE) 1499 (void)strlcat(buf, " preference", sizeof buf); 1500 if (r->status & RELAY_WAIT_SECRET) 1501 (void)strlcat(buf, " secret", sizeof buf); 1502 if (r->status & RELAY_WAIT_SOURCE) 1503 (void)strlcat(buf, " source", sizeof buf); 1504 if (r->status & RELAY_WAIT_CONNECTOR) 1505 (void)strlcat(buf, " connector", sizeof buf); 1506 log_debug("debug: mta: %s waiting for%s", 1507 mta_relay_to_text(r), buf); 1508 return; 1509 } 1510 1511 /* 1512 * We have pending task, and it's maybe time too try a new source. 1513 */ 1514 if (r->nextsource <= time(NULL)) 1515 mta_query_source(r); 1516 else { 1517 log_debug("debug: mta: scheduling relay %s in %llus...", 1518 mta_relay_to_text(r), 1519 (unsigned long long) r->nextsource - time(NULL)); 1520 runq_schedule_at(runq_relay, r->nextsource, r); 1521 r->status |= RELAY_WAIT_CONNECTOR; 1522 mta_relay_ref(r); 1523 } 1524 } 1525 1526 static void 1527 mta_flush(struct mta_relay *relay, int fail, const char *error) 1528 { 1529 struct mta_envelope *e; 1530 struct mta_task *task; 1531 const char *domain; 1532 void *iter; 1533 struct mta_connector *c; 1534 size_t n, r; 1535 1536 log_debug("debug: mta_flush(%s, %d, \"%s\")", 1537 mta_relay_to_text(relay), fail, error); 1538 1539 if (fail != IMSG_MTA_DELIVERY_TEMPFAIL && fail != IMSG_MTA_DELIVERY_PERMFAIL) 1540 fatalx("unexpected delivery status %d", fail); 1541 1542 n = 0; 1543 while ((task = TAILQ_FIRST(&relay->tasks))) { 1544 TAILQ_REMOVE(&relay->tasks, task, entry); 1545 while ((e = TAILQ_FIRST(&task->envelopes))) { 1546 TAILQ_REMOVE(&task->envelopes, e, entry); 1547 1548 /* 1549 * host was suspended, cache envelope id in hoststat tree 1550 * so that it can be retried when a delivery succeeds for 1551 * that domain. 1552 */ 1553 domain = strchr(e->dest, '@'); 1554 if (fail == IMSG_MTA_DELIVERY_TEMPFAIL && domain) { 1555 r = 0; 1556 iter = NULL; 1557 while (tree_iter(&relay->connectors, &iter, 1558 NULL, (void **)&c)) { 1559 if (c->flags & CONNECTOR_ERROR_ROUTE) 1560 r++; 1561 } 1562 if (tree_count(&relay->connectors) == r) 1563 mta_hoststat_cache(domain+1, e->id); 1564 } 1565 1566 mta_delivery_log(e, NULL, relay->domain->name, fail, error); 1567 mta_delivery_notify(e); 1568 1569 n++; 1570 } 1571 free(task->sender); 1572 free(task); 1573 } 1574 1575 stat_decrement("mta.task", relay->ntask); 1576 stat_decrement("mta.envelope", n); 1577 relay->ntask = 0; 1578 1579 /* release all waiting envelopes for the relay */ 1580 if (relay->state & RELAY_HOLDQ) { 1581 m_create(p_queue, IMSG_MTA_HOLDQ_RELEASE, 0, 0, -1); 1582 m_add_id(p_queue, relay->id); 1583 m_add_int(p_queue, -1); 1584 m_close(p_queue); 1585 } 1586 } 1587 1588 /* 1589 * Find a route to use for this connector 1590 */ 1591 static struct mta_route * 1592 mta_find_route(struct mta_connector *c, time_t now, int *limits, 1593 time_t *nextconn, struct mta_mx **pmx) 1594 { 1595 struct mta_route *route, *best; 1596 struct mta_limits *l = c->relay->limits; 1597 struct mta_mx *mx; 1598 int level, limit_host, limit_route; 1599 int family_mismatch, seen, suspended_route; 1600 time_t tm; 1601 1602 log_debug("debug: mta-routing: searching new route for %s...", 1603 mta_connector_to_text(c)); 1604 1605 tm = 0; 1606 limit_host = 0; 1607 limit_route = 0; 1608 suspended_route = 0; 1609 family_mismatch = 0; 1610 level = -1; 1611 best = NULL; 1612 seen = 0; 1613 1614 TAILQ_FOREACH(mx, &c->relay->domain->mxs, entry) { 1615 /* 1616 * New preference level 1617 */ 1618 if (mx->preference > level) { 1619 #ifndef IGNORE_MX_PREFERENCE 1620 /* 1621 * Use the current best MX if found. 1622 */ 1623 if (best) 1624 break; 1625 1626 /* 1627 * No candidate found. There are valid MXs at this 1628 * preference level but they reached their limit, or 1629 * we can't connect yet. 1630 */ 1631 if (limit_host || limit_route || tm) 1632 break; 1633 1634 /* 1635 * If we are a backup MX, do not relay to MXs with 1636 * a greater preference value. 1637 */ 1638 if (c->relay->backuppref >= 0 && 1639 mx->preference >= c->relay->backuppref) 1640 break; 1641 1642 /* 1643 * Start looking at MXs on this preference level. 1644 */ 1645 #endif 1646 level = mx->preference; 1647 } 1648 1649 if (mx->host->flags & HOST_IGNORE) 1650 continue; 1651 1652 /* Found a possibly valid mx */ 1653 seen++; 1654 1655 if ((c->source->sa && 1656 c->source->sa->sa_family != mx->host->sa->sa_family) || 1657 (l->family && l->family != mx->host->sa->sa_family)) { 1658 log_debug("debug: mta-routing: skipping host %s: AF mismatch", 1659 mta_host_to_text(mx->host)); 1660 family_mismatch = 1; 1661 continue; 1662 } 1663 1664 if (mx->host->nconn >= l->maxconn_per_host) { 1665 log_debug("debug: mta-routing: skipping host %s: too many connections", 1666 mta_host_to_text(mx->host)); 1667 limit_host = 1; 1668 continue; 1669 } 1670 1671 if (mx->host->lastconn + l->conndelay_host > now) { 1672 log_debug("debug: mta-routing: skipping host %s: cannot use before %llus", 1673 mta_host_to_text(mx->host), 1674 (unsigned long long) mx->host->lastconn + l->conndelay_host - now); 1675 if (tm == 0 || mx->host->lastconn + l->conndelay_host < tm) 1676 tm = mx->host->lastconn + l->conndelay_host; 1677 continue; 1678 } 1679 1680 route = mta_route(c->source, mx->host); 1681 1682 if (route->flags & ROUTE_DISABLED) { 1683 log_debug("debug: mta-routing: skipping route %s: suspend", 1684 mta_route_to_text(route)); 1685 suspended_route |= route->flags & ROUTE_DISABLED; 1686 mta_route_unref(route); /* from here */ 1687 continue; 1688 } 1689 1690 if (route->nconn && (route->flags & ROUTE_NEW)) { 1691 log_debug("debug: mta-routing: skipping route %s: not validated yet", 1692 mta_route_to_text(route)); 1693 limit_route = 1; 1694 mta_route_unref(route); /* from here */ 1695 continue; 1696 } 1697 1698 if (route->nconn >= l->maxconn_per_route) { 1699 log_debug("debug: mta-routing: skipping route %s: too many connections", 1700 mta_route_to_text(route)); 1701 limit_route = 1; 1702 mta_route_unref(route); /* from here */ 1703 continue; 1704 } 1705 1706 if (route->lastconn + l->conndelay_route > now) { 1707 log_debug("debug: mta-routing: skipping route %s: cannot use before %llus (delay after connect)", 1708 mta_route_to_text(route), 1709 (unsigned long long) route->lastconn + l->conndelay_route - now); 1710 if (tm == 0 || route->lastconn + l->conndelay_route < tm) 1711 tm = route->lastconn + l->conndelay_route; 1712 mta_route_unref(route); /* from here */ 1713 continue; 1714 } 1715 1716 if (route->lastdisc + l->discdelay_route > now) { 1717 log_debug("debug: mta-routing: skipping route %s: cannot use before %llus (delay after disconnect)", 1718 mta_route_to_text(route), 1719 (unsigned long long) route->lastdisc + l->discdelay_route - now); 1720 if (tm == 0 || route->lastdisc + l->discdelay_route < tm) 1721 tm = route->lastdisc + l->discdelay_route; 1722 mta_route_unref(route); /* from here */ 1723 continue; 1724 } 1725 1726 /* Use the route with the lowest number of connections. */ 1727 if (best && route->nconn >= best->nconn) { 1728 log_debug("debug: mta-routing: skipping route %s: current one is better", 1729 mta_route_to_text(route)); 1730 mta_route_unref(route); /* from here */ 1731 continue; 1732 } 1733 1734 if (best) 1735 mta_route_unref(best); /* from here */ 1736 best = route; 1737 *pmx = mx; 1738 log_debug("debug: mta-routing: selecting candidate route %s", 1739 mta_route_to_text(route)); 1740 } 1741 1742 if (best) 1743 return (best); 1744 1745 /* Order is important */ 1746 if (seen == 0) { 1747 log_info("smtp-out: No MX found for %s", 1748 mta_connector_to_text(c)); 1749 c->flags |= CONNECTOR_ERROR_MX; 1750 } 1751 else if (limit_route) { 1752 log_debug("debug: mta: hit route limit"); 1753 *limits |= CONNECTOR_LIMIT_ROUTE; 1754 } 1755 else if (limit_host) { 1756 log_debug("debug: mta: hit host limit"); 1757 *limits |= CONNECTOR_LIMIT_HOST; 1758 } 1759 else if (tm) { 1760 if (tm > *nextconn) 1761 *nextconn = tm; 1762 } 1763 else if (family_mismatch) { 1764 log_info("smtp-out: Address family mismatch on %s", 1765 mta_connector_to_text(c)); 1766 c->flags |= CONNECTOR_ERROR_FAMILY; 1767 } 1768 else if (suspended_route) { 1769 log_info("smtp-out: No valid route for %s", 1770 mta_connector_to_text(c)); 1771 if (suspended_route & ROUTE_DISABLED_NET) 1772 c->flags |= CONNECTOR_ERROR_ROUTE_NET; 1773 if (suspended_route & ROUTE_DISABLED_SMTP) 1774 c->flags |= CONNECTOR_ERROR_ROUTE_SMTP; 1775 } 1776 1777 return (NULL); 1778 } 1779 1780 static void 1781 mta_log(const struct mta_envelope *evp, const char *prefix, const char *source, 1782 const char *relay, const char *status) 1783 { 1784 log_info("%016"PRIx64" mta delivery evpid=%016"PRIx64" " 1785 "from=<%s> to=<%s> rcpt=<%s> source=\"%s\" " 1786 "relay=\"%s\" delay=%s result=\"%s\" stat=\"%s\"", 1787 evp->session, 1788 evp->id, 1789 evp->task->sender, 1790 evp->dest, 1791 evp->rcpt ? evp->rcpt : "-", 1792 source ? source : "-", 1793 relay, 1794 duration_to_text(time(NULL) - evp->creation), 1795 prefix, 1796 status); 1797 } 1798 1799 static struct mta_relay * 1800 mta_relay(struct envelope *e, struct relayhost *relayh) 1801 { 1802 struct dispatcher *dispatcher; 1803 struct mta_relay key, *r; 1804 1805 dispatcher = dict_xget(env->sc_dispatchers, e->dispatcher); 1806 1807 memset(&key, 0, sizeof key); 1808 1809 key.pki_name = dispatcher->u.remote.pki; 1810 key.ca_name = dispatcher->u.remote.ca; 1811 key.authtable = dispatcher->u.remote.auth; 1812 key.sourcetable = dispatcher->u.remote.source; 1813 key.helotable = dispatcher->u.remote.helo_source; 1814 key.heloname = dispatcher->u.remote.helo; 1815 key.srs = dispatcher->u.remote.srs; 1816 1817 if (relayh->hostname[0]) { 1818 key.domain = mta_domain(relayh->hostname, 1); 1819 } 1820 else { 1821 key.domain = mta_domain(e->dest.domain, 0); 1822 if (dispatcher->u.remote.backup) { 1823 key.backupname = dispatcher->u.remote.backupmx; 1824 if (key.backupname == NULL) 1825 key.backupname = e->smtpname; 1826 } 1827 } 1828 1829 key.tls = relayh->tls; 1830 key.flags |= relayh->flags; 1831 key.port = relayh->port; 1832 key.authlabel = relayh->authlabel; 1833 if (!key.authlabel[0]) 1834 key.authlabel = NULL; 1835 1836 if ((r = SPLAY_FIND(mta_relay_tree, &relays, &key)) == NULL) { 1837 r = xcalloc(1, sizeof *r); 1838 TAILQ_INIT(&r->tasks); 1839 r->id = generate_uid(); 1840 r->dispatcher = dispatcher; 1841 r->tls = key.tls; 1842 r->flags = key.flags; 1843 r->domain = key.domain; 1844 r->backupname = key.backupname ? 1845 xstrdup(key.backupname) : NULL; 1846 r->backuppref = -1; 1847 r->port = key.port; 1848 r->pki_name = key.pki_name ? xstrdup(key.pki_name) : NULL; 1849 r->ca_name = key.ca_name ? xstrdup(key.ca_name) : NULL; 1850 if (key.authtable) 1851 r->authtable = xstrdup(key.authtable); 1852 if (key.authlabel) 1853 r->authlabel = xstrdup(key.authlabel); 1854 if (key.sourcetable) 1855 r->sourcetable = xstrdup(key.sourcetable); 1856 if (key.helotable) 1857 r->helotable = xstrdup(key.helotable); 1858 if (key.heloname) 1859 r->heloname = xstrdup(key.heloname); 1860 r->srs = key.srs; 1861 SPLAY_INSERT(mta_relay_tree, &relays, r); 1862 stat_increment("mta.relay", 1); 1863 } else { 1864 mta_domain_unref(key.domain); /* from here */ 1865 } 1866 1867 r->refcount++; 1868 return (r); 1869 } 1870 1871 static void 1872 mta_relay_ref(struct mta_relay *r) 1873 { 1874 r->refcount++; 1875 } 1876 1877 static void 1878 mta_relay_unref(struct mta_relay *relay) 1879 { 1880 struct mta_connector *c; 1881 1882 if (--relay->refcount) 1883 return; 1884 1885 /* Make sure they are no envelopes held for this relay */ 1886 if (relay->state & RELAY_HOLDQ) { 1887 m_create(p_queue, IMSG_MTA_HOLDQ_RELEASE, 0, 0, -1); 1888 m_add_id(p_queue, relay->id); 1889 m_add_int(p_queue, 0); 1890 m_close(p_queue); 1891 } 1892 1893 log_debug("debug: mta: freeing %s", mta_relay_to_text(relay)); 1894 SPLAY_REMOVE(mta_relay_tree, &relays, relay); 1895 1896 while ((tree_poproot(&relay->connectors, NULL, (void**)&c))) 1897 mta_connector_free(c); 1898 1899 free(relay->authlabel); 1900 free(relay->authtable); 1901 free(relay->backupname); 1902 free(relay->pki_name); 1903 free(relay->ca_name); 1904 free(relay->helotable); 1905 free(relay->heloname); 1906 free(relay->secret); 1907 free(relay->sourcetable); 1908 1909 mta_domain_unref(relay->domain); /* from constructor */ 1910 free(relay); 1911 stat_decrement("mta.relay", 1); 1912 } 1913 1914 const char * 1915 mta_relay_to_text(struct mta_relay *relay) 1916 { 1917 static char buf[1024]; 1918 char tmp[32]; 1919 const char *sep = ","; 1920 1921 (void)snprintf(buf, sizeof buf, "[relay:%s", relay->domain->name); 1922 1923 if (relay->port) { 1924 (void)strlcat(buf, sep, sizeof buf); 1925 (void)snprintf(tmp, sizeof tmp, "port=%d", (int)relay->port); 1926 (void)strlcat(buf, tmp, sizeof buf); 1927 } 1928 1929 (void)strlcat(buf, sep, sizeof buf); 1930 switch(relay->tls) { 1931 case RELAY_TLS_OPPORTUNISTIC: 1932 (void)strlcat(buf, "smtp", sizeof buf); 1933 break; 1934 case RELAY_TLS_STARTTLS: 1935 (void)strlcat(buf, "smtp+tls", sizeof buf); 1936 break; 1937 case RELAY_TLS_SMTPS: 1938 (void)strlcat(buf, "smtps", sizeof buf); 1939 break; 1940 case RELAY_TLS_NO: 1941 if (relay->flags & RELAY_LMTP) 1942 (void)strlcat(buf, "lmtp", sizeof buf); 1943 else 1944 (void)strlcat(buf, "smtp+notls", sizeof buf); 1945 break; 1946 default: 1947 (void)strlcat(buf, "???", sizeof buf); 1948 } 1949 1950 if (relay->flags & RELAY_AUTH) { 1951 (void)strlcat(buf, sep, sizeof buf); 1952 (void)strlcat(buf, "auth=", sizeof buf); 1953 (void)strlcat(buf, relay->authtable, sizeof buf); 1954 (void)strlcat(buf, ":", sizeof buf); 1955 (void)strlcat(buf, relay->authlabel, sizeof buf); 1956 } 1957 1958 if (relay->pki_name) { 1959 (void)strlcat(buf, sep, sizeof buf); 1960 (void)strlcat(buf, "pki_name=", sizeof buf); 1961 (void)strlcat(buf, relay->pki_name, sizeof buf); 1962 } 1963 1964 if (relay->domain->as_host) { 1965 (void)strlcat(buf, sep, sizeof buf); 1966 (void)strlcat(buf, "mx", sizeof buf); 1967 } 1968 1969 if (relay->backupname) { 1970 (void)strlcat(buf, sep, sizeof buf); 1971 (void)strlcat(buf, "backup=", sizeof buf); 1972 (void)strlcat(buf, relay->backupname, sizeof buf); 1973 } 1974 1975 if (relay->sourcetable) { 1976 (void)strlcat(buf, sep, sizeof buf); 1977 (void)strlcat(buf, "sourcetable=", sizeof buf); 1978 (void)strlcat(buf, relay->sourcetable, sizeof buf); 1979 } 1980 1981 if (relay->helotable) { 1982 (void)strlcat(buf, sep, sizeof buf); 1983 (void)strlcat(buf, "helotable=", sizeof buf); 1984 (void)strlcat(buf, relay->helotable, sizeof buf); 1985 } 1986 1987 if (relay->heloname) { 1988 (void)strlcat(buf, sep, sizeof buf); 1989 (void)strlcat(buf, "heloname=", sizeof buf); 1990 (void)strlcat(buf, relay->heloname, sizeof buf); 1991 } 1992 1993 (void)strlcat(buf, "]", sizeof buf); 1994 1995 return (buf); 1996 } 1997 1998 static void 1999 mta_relay_show(struct mta_relay *r, struct mproc *p, uint32_t id, time_t t) 2000 { 2001 struct mta_connector *c; 2002 void *iter; 2003 char buf[1024], flags[1024], dur[64]; 2004 time_t to; 2005 2006 flags[0] = '\0'; 2007 2008 #define SHOWSTATUS(f, n) do { \ 2009 if (r->status & (f)) { \ 2010 if (flags[0]) \ 2011 (void)strlcat(flags, ",", sizeof(flags)); \ 2012 (void)strlcat(flags, (n), sizeof(flags)); \ 2013 } \ 2014 } while(0) 2015 2016 SHOWSTATUS(RELAY_WAIT_MX, "MX"); 2017 SHOWSTATUS(RELAY_WAIT_PREFERENCE, "preference"); 2018 SHOWSTATUS(RELAY_WAIT_SECRET, "secret"); 2019 SHOWSTATUS(RELAY_WAIT_LIMITS, "limits"); 2020 SHOWSTATUS(RELAY_WAIT_SOURCE, "source"); 2021 SHOWSTATUS(RELAY_WAIT_CONNECTOR, "connector"); 2022 #undef SHOWSTATUS 2023 2024 if (runq_pending(runq_relay, r, &to)) 2025 (void)snprintf(dur, sizeof(dur), "%s", duration_to_text(to - t)); 2026 else 2027 (void)strlcpy(dur, "-", sizeof(dur)); 2028 2029 (void)snprintf(buf, sizeof(buf), "%s refcount=%d ntask=%zu nconn=%zu lastconn=%s timeout=%s wait=%s%s", 2030 mta_relay_to_text(r), 2031 r->refcount, 2032 r->ntask, 2033 r->nconn, 2034 r->lastconn ? duration_to_text(t - r->lastconn) : "-", 2035 dur, 2036 flags, 2037 (r->state & RELAY_ONHOLD) ? "ONHOLD" : ""); 2038 m_compose(p, IMSG_CTL_MTA_SHOW_RELAYS, id, 0, -1, buf, strlen(buf) + 1); 2039 2040 iter = NULL; 2041 while (tree_iter(&r->connectors, &iter, NULL, (void **)&c)) { 2042 2043 if (runq_pending(runq_connector, c, &to)) 2044 (void)snprintf(dur, sizeof(dur), "%s", duration_to_text(to - t)); 2045 else 2046 (void)strlcpy(dur, "-", sizeof(dur)); 2047 2048 flags[0] = '\0'; 2049 2050 #define SHOWFLAG(f, n) do { \ 2051 if (c->flags & (f)) { \ 2052 if (flags[0]) \ 2053 (void)strlcat(flags, ",", sizeof(flags)); \ 2054 (void)strlcat(flags, (n), sizeof(flags)); \ 2055 } \ 2056 } while(0) 2057 2058 SHOWFLAG(CONNECTOR_NEW, "NEW"); 2059 SHOWFLAG(CONNECTOR_WAIT, "WAIT"); 2060 2061 SHOWFLAG(CONNECTOR_ERROR_FAMILY, "ERROR_FAMILY"); 2062 SHOWFLAG(CONNECTOR_ERROR_SOURCE, "ERROR_SOURCE"); 2063 SHOWFLAG(CONNECTOR_ERROR_MX, "ERROR_MX"); 2064 SHOWFLAG(CONNECTOR_ERROR_ROUTE_NET, "ERROR_ROUTE_NET"); 2065 SHOWFLAG(CONNECTOR_ERROR_ROUTE_SMTP, "ERROR_ROUTE_SMTP"); 2066 SHOWFLAG(CONNECTOR_ERROR_BLOCKED, "ERROR_BLOCKED"); 2067 2068 SHOWFLAG(CONNECTOR_LIMIT_HOST, "LIMIT_HOST"); 2069 SHOWFLAG(CONNECTOR_LIMIT_ROUTE, "LIMIT_ROUTE"); 2070 SHOWFLAG(CONNECTOR_LIMIT_SOURCE, "LIMIT_SOURCE"); 2071 SHOWFLAG(CONNECTOR_LIMIT_RELAY, "LIMIT_RELAY"); 2072 SHOWFLAG(CONNECTOR_LIMIT_CONN, "LIMIT_CONN"); 2073 SHOWFLAG(CONNECTOR_LIMIT_DOMAIN, "LIMIT_DOMAIN"); 2074 #undef SHOWFLAG 2075 2076 (void)snprintf(buf, sizeof(buf), 2077 " connector %s refcount=%d nconn=%zu lastconn=%s timeout=%s flags=%s", 2078 mta_source_to_text(c->source), 2079 c->refcount, 2080 c->nconn, 2081 c->lastconn ? duration_to_text(t - c->lastconn) : "-", 2082 dur, 2083 flags); 2084 m_compose(p, IMSG_CTL_MTA_SHOW_RELAYS, id, 0, -1, buf, 2085 strlen(buf) + 1); 2086 2087 2088 } 2089 } 2090 2091 static int 2092 mta_relay_cmp(const struct mta_relay *a, const struct mta_relay *b) 2093 { 2094 int r; 2095 2096 if (a->domain < b->domain) 2097 return (-1); 2098 if (a->domain > b->domain) 2099 return (1); 2100 2101 if (a->tls < b->tls) 2102 return (-1); 2103 if (a->tls > b->tls) 2104 return (1); 2105 2106 if (a->flags < b->flags) 2107 return (-1); 2108 if (a->flags > b->flags) 2109 return (1); 2110 2111 if (a->port < b->port) 2112 return (-1); 2113 if (a->port > b->port) 2114 return (1); 2115 2116 if (a->authtable == NULL && b->authtable) 2117 return (-1); 2118 if (a->authtable && b->authtable == NULL) 2119 return (1); 2120 if (a->authtable && ((r = strcmp(a->authtable, b->authtable)))) 2121 return (r); 2122 if (a->authlabel == NULL && b->authlabel) 2123 return (-1); 2124 if (a->authlabel && b->authlabel == NULL) 2125 return (1); 2126 if (a->authlabel && ((r = strcmp(a->authlabel, b->authlabel)))) 2127 return (r); 2128 if (a->sourcetable == NULL && b->sourcetable) 2129 return (-1); 2130 if (a->sourcetable && b->sourcetable == NULL) 2131 return (1); 2132 if (a->sourcetable && ((r = strcmp(a->sourcetable, b->sourcetable)))) 2133 return (r); 2134 if (a->helotable == NULL && b->helotable) 2135 return (-1); 2136 if (a->helotable && b->helotable == NULL) 2137 return (1); 2138 if (a->helotable && ((r = strcmp(a->helotable, b->helotable)))) 2139 return (r); 2140 if (a->heloname == NULL && b->heloname) 2141 return (-1); 2142 if (a->heloname && b->heloname == NULL) 2143 return (1); 2144 if (a->heloname && ((r = strcmp(a->heloname, b->heloname)))) 2145 return (r); 2146 2147 if (a->pki_name == NULL && b->pki_name) 2148 return (-1); 2149 if (a->pki_name && b->pki_name == NULL) 2150 return (1); 2151 if (a->pki_name && ((r = strcmp(a->pki_name, b->pki_name)))) 2152 return (r); 2153 2154 if (a->ca_name == NULL && b->ca_name) 2155 return (-1); 2156 if (a->ca_name && b->ca_name == NULL) 2157 return (1); 2158 if (a->ca_name && ((r = strcmp(a->ca_name, b->ca_name)))) 2159 return (r); 2160 2161 if (a->backupname == NULL && b->backupname) 2162 return (-1); 2163 if (a->backupname && b->backupname == NULL) 2164 return (1); 2165 if (a->backupname && ((r = strcmp(a->backupname, b->backupname)))) 2166 return (r); 2167 2168 if (a->srs < b->srs) 2169 return (-1); 2170 if (a->srs > b->srs) 2171 return (1); 2172 2173 return (0); 2174 } 2175 2176 SPLAY_GENERATE(mta_relay_tree, mta_relay, entry, mta_relay_cmp); 2177 2178 static struct mta_host * 2179 mta_host(const struct sockaddr *sa) 2180 { 2181 struct mta_host key, *h; 2182 struct sockaddr_storage ss; 2183 2184 memmove(&ss, sa, sa->sa_len); 2185 key.sa = (struct sockaddr*)&ss; 2186 h = SPLAY_FIND(mta_host_tree, &hosts, &key); 2187 2188 if (h == NULL) { 2189 h = xcalloc(1, sizeof(*h)); 2190 h->sa = xmemdup(sa, sa->sa_len); 2191 SPLAY_INSERT(mta_host_tree, &hosts, h); 2192 stat_increment("mta.host", 1); 2193 } 2194 2195 h->refcount++; 2196 return (h); 2197 } 2198 2199 static void 2200 mta_host_ref(struct mta_host *h) 2201 { 2202 h->refcount++; 2203 } 2204 2205 static void 2206 mta_host_unref(struct mta_host *h) 2207 { 2208 if (--h->refcount) 2209 return; 2210 2211 SPLAY_REMOVE(mta_host_tree, &hosts, h); 2212 free(h->sa); 2213 free(h->ptrname); 2214 free(h); 2215 stat_decrement("mta.host", 1); 2216 } 2217 2218 const char * 2219 mta_host_to_text(struct mta_host *h) 2220 { 2221 static char buf[1024]; 2222 2223 if (h->ptrname) 2224 (void)snprintf(buf, sizeof buf, "%s (%s)", 2225 sa_to_text(h->sa), h->ptrname); 2226 else 2227 (void)snprintf(buf, sizeof buf, "%s", sa_to_text(h->sa)); 2228 2229 return (buf); 2230 } 2231 2232 static int 2233 mta_host_cmp(const struct mta_host *a, const struct mta_host *b) 2234 { 2235 if (a->sa->sa_len < b->sa->sa_len) 2236 return (-1); 2237 if (a->sa->sa_len > b->sa->sa_len) 2238 return (1); 2239 return (memcmp(a->sa, b->sa, a->sa->sa_len)); 2240 } 2241 2242 SPLAY_GENERATE(mta_host_tree, mta_host, entry, mta_host_cmp); 2243 2244 static struct mta_domain * 2245 mta_domain(char *name, int as_host) 2246 { 2247 struct mta_domain key, *d; 2248 2249 key.name = name; 2250 key.as_host = as_host; 2251 d = SPLAY_FIND(mta_domain_tree, &domains, &key); 2252 2253 if (d == NULL) { 2254 d = xcalloc(1, sizeof(*d)); 2255 d->name = xstrdup(name); 2256 d->as_host = as_host; 2257 TAILQ_INIT(&d->mxs); 2258 SPLAY_INSERT(mta_domain_tree, &domains, d); 2259 stat_increment("mta.domain", 1); 2260 } 2261 2262 d->refcount++; 2263 return (d); 2264 } 2265 2266 #if 0 2267 static void 2268 mta_domain_ref(struct mta_domain *d) 2269 { 2270 d->refcount++; 2271 } 2272 #endif 2273 2274 static void 2275 mta_domain_unref(struct mta_domain *d) 2276 { 2277 struct mta_mx *mx; 2278 2279 if (--d->refcount) 2280 return; 2281 2282 while ((mx = TAILQ_FIRST(&d->mxs))) { 2283 TAILQ_REMOVE(&d->mxs, mx, entry); 2284 mta_host_unref(mx->host); /* from IMSG_DNS_HOST */ 2285 free(mx->mxname); 2286 free(mx); 2287 } 2288 2289 SPLAY_REMOVE(mta_domain_tree, &domains, d); 2290 free(d->name); 2291 free(d); 2292 stat_decrement("mta.domain", 1); 2293 } 2294 2295 static int 2296 mta_domain_cmp(const struct mta_domain *a, const struct mta_domain *b) 2297 { 2298 if (a->as_host < b->as_host) 2299 return (-1); 2300 if (a->as_host > b->as_host) 2301 return (1); 2302 return (strcasecmp(a->name, b->name)); 2303 } 2304 2305 SPLAY_GENERATE(mta_domain_tree, mta_domain, entry, mta_domain_cmp); 2306 2307 static struct mta_source * 2308 mta_source(const struct sockaddr *sa) 2309 { 2310 struct mta_source key, *s; 2311 struct sockaddr_storage ss; 2312 2313 if (sa) { 2314 memmove(&ss, sa, sa->sa_len); 2315 key.sa = (struct sockaddr*)&ss; 2316 } else 2317 key.sa = NULL; 2318 s = SPLAY_FIND(mta_source_tree, &sources, &key); 2319 2320 if (s == NULL) { 2321 s = xcalloc(1, sizeof(*s)); 2322 if (sa) 2323 s->sa = xmemdup(sa, sa->sa_len); 2324 SPLAY_INSERT(mta_source_tree, &sources, s); 2325 stat_increment("mta.source", 1); 2326 } 2327 2328 s->refcount++; 2329 return (s); 2330 } 2331 2332 static void 2333 mta_source_ref(struct mta_source *s) 2334 { 2335 s->refcount++; 2336 } 2337 2338 static void 2339 mta_source_unref(struct mta_source *s) 2340 { 2341 if (--s->refcount) 2342 return; 2343 2344 SPLAY_REMOVE(mta_source_tree, &sources, s); 2345 free(s->sa); 2346 free(s); 2347 stat_decrement("mta.source", 1); 2348 } 2349 2350 static const char * 2351 mta_source_to_text(struct mta_source *s) 2352 { 2353 static char buf[1024]; 2354 2355 if (s->sa == NULL) 2356 return "[]"; 2357 (void)snprintf(buf, sizeof buf, "%s", sa_to_text(s->sa)); 2358 return (buf); 2359 } 2360 2361 static int 2362 mta_source_cmp(const struct mta_source *a, const struct mta_source *b) 2363 { 2364 if (a->sa == NULL) 2365 return ((b->sa == NULL) ? 0 : -1); 2366 if (b->sa == NULL) 2367 return (1); 2368 if (a->sa->sa_len < b->sa->sa_len) 2369 return (-1); 2370 if (a->sa->sa_len > b->sa->sa_len) 2371 return (1); 2372 return (memcmp(a->sa, b->sa, a->sa->sa_len)); 2373 } 2374 2375 SPLAY_GENERATE(mta_source_tree, mta_source, entry, mta_source_cmp); 2376 2377 static struct mta_connector * 2378 mta_connector(struct mta_relay *relay, struct mta_source *source) 2379 { 2380 struct mta_connector *c; 2381 2382 c = tree_get(&relay->connectors, (uintptr_t)(source)); 2383 if (c == NULL) { 2384 c = xcalloc(1, sizeof(*c)); 2385 c->relay = relay; 2386 c->source = source; 2387 c->flags |= CONNECTOR_NEW; 2388 mta_source_ref(source); 2389 tree_xset(&relay->connectors, (uintptr_t)(source), c); 2390 stat_increment("mta.connector", 1); 2391 log_debug("debug: mta: new %s", mta_connector_to_text(c)); 2392 } 2393 2394 return (c); 2395 } 2396 2397 static void 2398 mta_connector_free(struct mta_connector *c) 2399 { 2400 log_debug("debug: mta: freeing %s", 2401 mta_connector_to_text(c)); 2402 2403 if (c->flags & CONNECTOR_WAIT) { 2404 log_debug("debug: mta: cancelling timeout for %s", 2405 mta_connector_to_text(c)); 2406 runq_cancel(runq_connector, c); 2407 } 2408 mta_source_unref(c->source); /* from constructor */ 2409 free(c); 2410 2411 stat_decrement("mta.connector", 1); 2412 } 2413 2414 static const char * 2415 mta_connector_to_text(struct mta_connector *c) 2416 { 2417 static char buf[1024]; 2418 2419 (void)snprintf(buf, sizeof buf, "[connector:%s->%s,0x%x]", 2420 mta_source_to_text(c->source), 2421 mta_relay_to_text(c->relay), 2422 c->flags); 2423 return (buf); 2424 } 2425 2426 static struct mta_route * 2427 mta_route(struct mta_source *src, struct mta_host *dst) 2428 { 2429 struct mta_route key, *r; 2430 static uint64_t rid = 0; 2431 2432 key.src = src; 2433 key.dst = dst; 2434 r = SPLAY_FIND(mta_route_tree, &routes, &key); 2435 2436 if (r == NULL) { 2437 r = xcalloc(1, sizeof(*r)); 2438 r->src = src; 2439 r->dst = dst; 2440 r->flags |= ROUTE_NEW; 2441 r->id = ++rid; 2442 SPLAY_INSERT(mta_route_tree, &routes, r); 2443 mta_source_ref(src); 2444 mta_host_ref(dst); 2445 stat_increment("mta.route", 1); 2446 } 2447 else if (r->flags & ROUTE_RUNQ) { 2448 log_debug("debug: mta: mta_route_ref(): cancelling runq for route %s", 2449 mta_route_to_text(r)); 2450 r->flags &= ~(ROUTE_RUNQ | ROUTE_KEEPALIVE); 2451 runq_cancel(runq_route, r); 2452 r->refcount--; /* from mta_route_unref() */ 2453 } 2454 2455 r->refcount++; 2456 return (r); 2457 } 2458 2459 static void 2460 mta_route_ref(struct mta_route *r) 2461 { 2462 r->refcount++; 2463 } 2464 2465 static void 2466 mta_route_unref(struct mta_route *r) 2467 { 2468 time_t sched, now; 2469 int delay; 2470 2471 if (--r->refcount) 2472 return; 2473 2474 /* 2475 * Nothing references this route, but we might want to keep it alive 2476 * for a while. 2477 */ 2478 now = time(NULL); 2479 sched = 0; 2480 2481 if (r->penalty) { 2482 #if DELAY_QUADRATIC 2483 delay = DELAY_ROUTE_BASE * r->penalty * r->penalty; 2484 #else 2485 delay = 15 * 60; 2486 #endif 2487 if (delay > DELAY_ROUTE_MAX) 2488 delay = DELAY_ROUTE_MAX; 2489 sched = r->lastpenalty + delay; 2490 log_debug("debug: mta: mta_route_unref(): keeping route %s alive for %llus (penalty %d)", 2491 mta_route_to_text(r), (unsigned long long) sched - now, r->penalty); 2492 } else if (!(r->flags & ROUTE_KEEPALIVE)) { 2493 if (r->lastconn + max_seen_conndelay_route > now) 2494 sched = r->lastconn + max_seen_conndelay_route; 2495 if (r->lastdisc + max_seen_discdelay_route > now && 2496 r->lastdisc + max_seen_discdelay_route < sched) 2497 sched = r->lastdisc + max_seen_discdelay_route; 2498 2499 if (sched > now) 2500 log_debug("debug: mta: mta_route_unref(): keeping route %s alive for %llus (imposed delay)", 2501 mta_route_to_text(r), (unsigned long long) sched - now); 2502 } 2503 2504 if (sched > now) { 2505 r->flags |= ROUTE_RUNQ; 2506 runq_schedule_at(runq_route, sched, r); 2507 r->refcount++; 2508 return; 2509 } 2510 2511 log_debug("debug: mta: mta_route_unref(): really discarding route %s", 2512 mta_route_to_text(r)); 2513 2514 SPLAY_REMOVE(mta_route_tree, &routes, r); 2515 mta_source_unref(r->src); /* from constructor */ 2516 mta_host_unref(r->dst); /* from constructor */ 2517 free(r); 2518 stat_decrement("mta.route", 1); 2519 } 2520 2521 static const char * 2522 mta_route_to_text(struct mta_route *r) 2523 { 2524 static char buf[1024]; 2525 2526 (void)snprintf(buf, sizeof buf, "%s <-> %s", 2527 mta_source_to_text(r->src), 2528 mta_host_to_text(r->dst)); 2529 2530 return (buf); 2531 } 2532 2533 static int 2534 mta_route_cmp(const struct mta_route *a, const struct mta_route *b) 2535 { 2536 if (a->src < b->src) 2537 return (-1); 2538 if (a->src > b->src) 2539 return (1); 2540 2541 if (a->dst < b->dst) 2542 return (-1); 2543 if (a->dst > b->dst) 2544 return (1); 2545 2546 return (0); 2547 } 2548 2549 SPLAY_GENERATE(mta_route_tree, mta_route, entry, mta_route_cmp); 2550 2551 void 2552 mta_block(struct mta_source *src, char *dom) 2553 { 2554 struct mta_block key, *b; 2555 2556 key.source = src; 2557 key.domain = dom; 2558 2559 b = SPLAY_FIND(mta_block_tree, &blocks, &key); 2560 if (b != NULL) 2561 return; 2562 2563 b = xcalloc(1, sizeof(*b)); 2564 if (dom) 2565 b->domain = xstrdup(dom); 2566 b->source = src; 2567 mta_source_ref(src); 2568 SPLAY_INSERT(mta_block_tree, &blocks, b); 2569 } 2570 2571 void 2572 mta_unblock(struct mta_source *src, char *dom) 2573 { 2574 struct mta_block key, *b; 2575 2576 key.source = src; 2577 key.domain = dom; 2578 2579 b = SPLAY_FIND(mta_block_tree, &blocks, &key); 2580 if (b == NULL) 2581 return; 2582 2583 SPLAY_REMOVE(mta_block_tree, &blocks, b); 2584 2585 mta_source_unref(b->source); 2586 free(b->domain); 2587 free(b); 2588 } 2589 2590 int 2591 mta_is_blocked(struct mta_source *src, char *dom) 2592 { 2593 struct mta_block key; 2594 2595 key.source = src; 2596 key.domain = dom; 2597 2598 if (SPLAY_FIND(mta_block_tree, &blocks, &key)) 2599 return (1); 2600 2601 return (0); 2602 } 2603 2604 static 2605 int 2606 mta_block_cmp(const struct mta_block *a, const struct mta_block *b) 2607 { 2608 if (a->source < b->source) 2609 return (-1); 2610 if (a->source > b->source) 2611 return (1); 2612 if (!a->domain && b->domain) 2613 return (-1); 2614 if (a->domain && !b->domain) 2615 return (1); 2616 if (a->domain == b->domain) 2617 return (0); 2618 return (strcasecmp(a->domain, b->domain)); 2619 } 2620 2621 SPLAY_GENERATE(mta_block_tree, mta_block, entry, mta_block_cmp); 2622 2623 2624 2625 /* hoststat errors are not critical, we do best effort */ 2626 void 2627 mta_hoststat_update(const char *host, const char *error) 2628 { 2629 struct hoststat *hs = NULL; 2630 char buf[HOST_NAME_MAX+1]; 2631 2632 if (!lowercase(buf, host, sizeof buf)) 2633 return; 2634 2635 hs = dict_get(&hoststat, buf); 2636 if (hs == NULL) { 2637 if ((hs = calloc(1, sizeof *hs)) == NULL) 2638 return; 2639 tree_init(&hs->deferred); 2640 runq_schedule(runq_hoststat, HOSTSTAT_EXPIRE_DELAY, hs); 2641 } 2642 (void)strlcpy(hs->name, buf, sizeof hs->name); 2643 (void)strlcpy(hs->error, error, sizeof hs->error); 2644 hs->tm = time(NULL); 2645 dict_set(&hoststat, buf, hs); 2646 2647 runq_cancel(runq_hoststat, hs); 2648 runq_schedule(runq_hoststat, HOSTSTAT_EXPIRE_DELAY, hs); 2649 } 2650 2651 void 2652 mta_hoststat_cache(const char *host, uint64_t evpid) 2653 { 2654 struct hoststat *hs = NULL; 2655 char buf[HOST_NAME_MAX+1]; 2656 2657 if (!lowercase(buf, host, sizeof buf)) 2658 return; 2659 2660 hs = dict_get(&hoststat, buf); 2661 if (hs == NULL) 2662 return; 2663 2664 if (tree_count(&hs->deferred) >= env->sc_mta_max_deferred) 2665 return; 2666 2667 tree_set(&hs->deferred, evpid, NULL); 2668 } 2669 2670 void 2671 mta_hoststat_uncache(const char *host, uint64_t evpid) 2672 { 2673 struct hoststat *hs = NULL; 2674 char buf[HOST_NAME_MAX+1]; 2675 2676 if (!lowercase(buf, host, sizeof buf)) 2677 return; 2678 2679 hs = dict_get(&hoststat, buf); 2680 if (hs == NULL) 2681 return; 2682 2683 tree_pop(&hs->deferred, evpid); 2684 } 2685 2686 void 2687 mta_hoststat_reschedule(const char *host) 2688 { 2689 struct hoststat *hs = NULL; 2690 char buf[HOST_NAME_MAX+1]; 2691 uint64_t evpid; 2692 2693 if (!lowercase(buf, host, sizeof buf)) 2694 return; 2695 2696 hs = dict_get(&hoststat, buf); 2697 if (hs == NULL) 2698 return; 2699 2700 while (tree_poproot(&hs->deferred, &evpid, NULL)) { 2701 m_compose(p_queue, IMSG_MTA_SCHEDULE, 0, 0, -1, 2702 &evpid, sizeof evpid); 2703 } 2704 } 2705 2706 static void 2707 mta_hoststat_remove_entry(struct hoststat *hs) 2708 { 2709 while (tree_poproot(&hs->deferred, NULL, NULL)) 2710 ; 2711 dict_pop(&hoststat, hs->name); 2712 runq_cancel(runq_hoststat, hs); 2713 } 2714