#endif
)
{
-address_item *addr;
int orvalue = 0;
if (errno_value == ERRNO_CONNECTTIMEOUT)
{
errno_value = ETIMEDOUT;
orvalue = RTEF_CTOUT;
}
-for (addr = addrlist; addr; addr = addr->next)
+for (address_item * addr = addrlist; addr; addr = addr->next)
if (addr->transport_return >= PENDING)
{
addr->basic_errno = errno_value;
pl, smtp_command, s);
return FALSE;
+ case ERRNO_TLSFAILURE: /* Handle bad first read; can happen with
+ GnuTLS and TLS1.3 */
+ *message = US"bad first read from TLS conn";
+ return TRUE;
+
case ERRNO_FILTER_FAIL: /* Handle a failed filter process error;
can't send QUIT as we mustn't end the DATA. */
*message = string_sprintf("transport filter process failed (%d)%s",
uschar * ehlo_resp_key = ehlo_cache_key(sx);
dbdata_ehlo_resp er = { .data = sx->ehlo_resp };
+ HDEBUG(D_transport) debug_printf("writing clr %04x/%04x cry %04x/%04x\n",
+ sx->ehlo_resp.cleartext_features, sx->ehlo_resp.cleartext_auths,
+ sx->ehlo_resp.crypted_features, sx->ehlo_resp.crypted_auths);
+
dbfn_write(dbm_file, ehlo_resp_key, &er, (int)sizeof(er));
dbfn_close(dbm_file);
}
Return:
OK all well
+ DEFER error on first read of TLS'd conn
FAIL SMTP error in response
*/
int
{
BOOL pending_BANNER = sx->pending_BANNER;
BOOL pending_EHLO = sx->pending_EHLO;
+int rc = FAIL;
sx->pending_BANNER = FALSE; /* clear early to avoid recursion */
sx->pending_EHLO = FALSE;
if (!smtp_reap_banner(sx))
{
DEBUG(D_transport) debug_printf("bad banner\n");
+ if (tls_out.active.sock >= 0) rc = DEFER;
goto fail;
}
}
if (!smtp_reap_ehlo(sx))
{
DEBUG(D_transport) debug_printf("bad response for EHLO\n");
+ if (tls_out.active.sock >= 0) rc = DEFER;
goto fail;
}
|| (authbits = study_ehlo_auths(sx)) != *ap)
{
HDEBUG(D_transport)
- debug_printf("EHLO extensions changed, 0x%04x/0x%04x -> 0x%04x/0x%04x\n",
+ debug_printf("EHLO %s extensions changed, 0x%04x/0x%04x -> 0x%04x/0x%04x\n",
+ tls_out.active.sock < 0 ? "cleartext" : "crypted",
sx->peer_offered, *ap, peer_offered, authbits);
+ *(tls_out.active.sock < 0
+ ? &sx->ehlo_resp.cleartext_features : &sx->ehlo_resp.crypted_features) = peer_offered;
*ap = authbits;
if (peer_offered & OPTION_EARLY_PIPE)
write_ehlo_cache_entry(sx);
fail:
invalidate_ehlo_cache_entry(sx);
(void) smtp_discard_responses(sx, sx->conn_args.ob, *countp);
- return FAIL;
+ return rc;
}
#endif
-2 I/O or other non-response error for RCPT
-3 DATA or MAIL failed - errno and buffer set
-4 banner or EHLO failed (early-pipelining)
+ -5 banner or EHLO failed (early-pipelining, TLS)
*/
static int
address_item * addr = sx->sync_addr;
smtp_transport_options_block * ob = sx->conn_args.ob;
int yield = 0;
+int rc;
#ifdef EXPERIMENTAL_PIPE_CONNECT
-if (smtp_reap_early_pipe(sx, &count) != OK)
- return -4;
+if ((rc = smtp_reap_early_pipe(sx, &count)) != OK)
+ return rc == FAIL ? -4 : -5;
#endif
/* Handle the response for a MAIL command. On error, reinstate the original
{
DEBUG(D_transport) debug_printf("bad response for MAIL\n");
Ustrcpy(big_buffer, mail_command); /* Fits, because it came from there! */
+ if (errno == ERRNO_TLSFAILURE)
+ return -5;
if (errno == 0 && sx->buffer[0] != 0)
{
int save_errno = 0;
}
}
+ /* Error on first TLS read */
+
+ else if (errno == ERRNO_TLSFAILURE)
+ return -5;
+
/* Timeout while reading the response */
else if (errno == ETIMEDOUT)
int code;
uschar *msg;
BOOL pass_message;
+
+ if (errno == ERRNO_TLSFAILURE) /* Error on first TLS read */
+ return -5;
+
if (pending_DATA > 0 || (yield & 1) != 0)
{
if (errno == 0 && sx->buffer[0] == '4')
If one is found, attempt to authenticate by calling its client function.
*/
- for (au = auths; !f.smtp_authenticated && au; au = au->next)
+ for (auth_instance * au = auths; !f.smtp_authenticated && au; au = au->next)
{
uschar *p = names;
DEBUG(D_transport)
{
dns_scan dnss;
- dns_record * rr;
- for (rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS); rr;
+ for (dns_record * rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS); rr;
rr = dns_next_rr(dnsa, &dnss, RESET_NEXT))
if (rr->type == T_TLSA && rr->size > 3)
{
tc_chunk_last add LAST option to SMTP BDAT command
tc_reap_prev reap response to previous SMTP commands
-Returns: OK or ERROR
+Returns:
+ OK or ERROR
+ DEFER TLS error on first read (EHLO-resp); errno set
*/
static int
case 2: sx->completed_addr = TRUE; /* 5xx (only) => progress made */
case 0: break; /* No 2xx or 5xx, but no probs */
- case -1: /* Timeout on RCPT */
+ case -5: errno = ERRNO_TLSFAILURE;
+ return DEFER;
#ifdef EXPERIMENTAL_PIPE_CONNECT
case -4: /* non-2xx for pipelined banner or EHLO */
#endif
+ case -1: /* Timeout on RCPT */
default: return ERROR; /* I/O error, or any MAIL/DATA error */
}
cmd_count = 1;
int
smtp_setup_conn(smtp_context * sx, BOOL suppress_tls)
{
-#if defined(SUPPORT_TLS) && defined(SUPPORT_DANE)
-dns_answer tlsa_dnsa;
-#endif
smtp_transport_options_block * ob = sx->conn_args.tblock->options_block;
BOOL pass_message = FALSE;
uschar * message = NULL;
int yield = OK;
int rc;
+#ifdef SUPPORT_TLS
+uschar * tls_errstr;
+#endif
sx->conn_args.ob = ob;
#endif
sx->dsn_all_lasthop = TRUE;
#if defined(SUPPORT_TLS) && defined(SUPPORT_DANE)
-sx->dane = FALSE;
+sx->conn_args.dane = FALSE;
sx->dane_required =
verify_check_given_host(CUSS &ob->hosts_require_dane, sx->conn_args.host) == OK;
#endif
if( sx->dane_required
|| verify_check_given_host(CUSS &ob->hosts_try_dane, sx->conn_args.host) == OK
)
- switch (rc = tlsa_lookup(sx->conn_args.host, &tlsa_dnsa, sx->dane_required))
+ switch (rc = tlsa_lookup(sx->conn_args.host, &sx->conn_args.tlsa_dnsa, sx->dane_required))
{
- case OK: sx->dane = TRUE;
+ case OK: sx->conn_args.dane = TRUE;
ob->tls_tempfail_tryclear = FALSE;
break;
case FAIL_FORCED: break;
default: set_errno_nohost(sx->addrlist, ERRNO_DNSDEFER,
string_sprintf("DANE error: tlsa lookup %s",
- rc == DEFER ? "DEFER" : "FAIL"),
+ rc_to_string(rc)),
rc, FALSE);
# ifndef DISABLE_EVENT
(void) event_raise(sx->conn_args.tblock->event_action,
else
TLS_NEGOTIATE:
{
- address_item * addr;
- uschar * errstr;
- sx->cctx.tls_ctx = tls_client_start(sx->cctx.sock, sx->conn_args.host,
- sx->addrlist, sx->conn_args.tblock,
-# ifdef SUPPORT_DANE
- sx->dane ? &tlsa_dnsa : NULL,
-# endif
- &tls_out, &errstr);
-
- if (!sx->cctx.tls_ctx)
+ if (!tls_client_start(&sx->cctx, &sx->conn_args, sx->addrlist, &tls_out, &tls_errstr))
{
/* TLS negotiation failed; give an error. From outside, this function may
be called again to try in clear on a new connection, if the options permit
it for this host. */
- DEBUG(D_tls) debug_printf("TLS session fail: %s\n", errstr);
+GNUTLS_CONN_FAILED:
+ DEBUG(D_tls) debug_printf("TLS session fail: %s\n", tls_errstr);
# ifdef SUPPORT_DANE
- if (sx->dane)
+ if (sx->conn_args.dane)
{
log_write(0, LOG_MAIN,
"DANE attempt failed; TLS connection to %s [%s]: %s",
- sx->conn_args.host->name, sx->conn_args.host->address, errstr);
+ sx->conn_args.host->name, sx->conn_args.host->address, tls_errstr);
# ifndef DISABLE_EVENT
(void) event_raise(sx->conn_args.tblock->event_action,
US"dane:fail", US"validation-failure"); /* could do with better detail */
# endif
errno = ERRNO_TLSFAILURE;
- message = string_sprintf("TLS session: %s", errstr);
+ message = string_sprintf("TLS session: %s", tls_errstr);
sx->send_quit = FALSE;
goto TLS_FAILED;
}
/* TLS session is set up */
smtp_peer_options_wrap = smtp_peer_options;
- for (addr = sx->addrlist; addr; addr = addr->next)
+ for (address_item * addr = sx->addrlist; addr; addr = addr->next)
if (addr->transport_return == PENDING_DEFER)
{
addr->cipher = tls_out.cipher;
#endif
{
if (!smtp_reap_ehlo(sx))
+#ifdef USE_GNUTLS
+ {
+ /* The GnuTLS layer in Exim only spots a server-rejection of a client
+ cert late, under TLS1.3 - which means here; the first time we try to
+ receive crypted data. Treat it as if it was a connect-time failure.
+ See also the early-pipe equivalent... which will be hard; every call
+ to sync_responses will need to check the result.
+ It would be nicer to have GnuTLS check the cert during the handshake.
+ Can it do that, with all the flexibility we need? */
+
+ tls_errstr = US"error on first read";
+ goto GNUTLS_CONN_FAILED;
+ }
+#else
goto RESPONSE_FAILED;
+#endif
smtp_peer_options = 0;
}
}
else if ( sx->smtps
# ifdef SUPPORT_DANE
- || sx->dane
+ || sx->conn_args.dane
# endif
# ifdef EXPERIMENTAL_REQUIRETLS
|| tls_requiretls & REQUIRETLS_MSG
smtp_peer_options & OPTION_TLS
? "an attempt to start TLS failed" : "the server did not offer TLS support");
# if defined(SUPPORT_DANE) && !defined(DISABLE_EVENT)
- if (sx->dane)
+ if (sx->conn_args.dane)
(void) event_raise(sx->conn_args.tblock->event_action, US"dane:fail",
smtp_peer_options & OPTION_TLS
? US"validation-failure" /* could do with better detail */
{
shutdown(sx->cctx.sock, SHUT_WR);
if (fcntl(sx->cctx.sock, F_SETFL, O_NONBLOCK) == 0)
- for (rc = 16; read(sx->cctx.sock, sx->inbuffer, sizeof(sx->inbuffer)) > 0 && rc > 0;)
- rc--; /* drain socket */
+ for (int i = 16; read(sx->cctx.sock, sx->inbuffer, sizeof(sx->inbuffer)) > 0 && i > 0;)
+ i--; /* drain socket */
sx->send_quit = FALSE;
}
(void)close(sx->cctx.sock);
sx->prdr_active = FALSE;
if (sx->peer_offered & OPTION_PRDR)
- for (addr = addrlist; addr; addr = addr->next)
+ for (address_item * addr = addrlist; addr; addr = addr->next)
if (addr->transport_return == PENDING_DEFER)
{
for (addr = addr->next; addr; addr = addr->next)
{
if (addr->dsn_flags & rf_dsnflags)
{
- int i;
BOOL first = TRUE;
Ustrcpy(p, " NOTIFY=");
while (*p) p++;
- for (i = 0; i < nelem(rf_list); i++) if (addr->dsn_flags & rf_list[i])
+ for (int i = 0; i < nelem(rf_list); i++) if (addr->dsn_flags & rf_list[i])
{
if (!first) *p++ = ',';
first = FALSE;
#ifdef EXPERIMENTAL_PIPE_CONNECT
case -4: return -1; /* non-2xx for pipelined banner or EHLO */
+ case -5: return -1; /* TLS first-read error */
#endif
}
sx->pending_MAIL = FALSE; /* Dealt with MAIL */
{
fd_set rfds, efds;
int max_fd = MAX(pfd[0], tls_out.active.sock) + 1;
-int rc, i, fd_bits, nbytes;
+int rc, i;
close(pfd[1]);
if ((rc = fork()))
FD_SET(tls_out.active.sock, &rfds);
FD_SET(pfd[0], &rfds);
-for (fd_bits = 3; fd_bits; )
+for (int fd_bits = 3; fd_bits; )
{
time_t time_left = timeout;
time_t time_start = time(NULL);
}
else
{
- for (nbytes = 0; rc - nbytes > 0; nbytes += i)
+ for (int nbytes = 0; rc - nbytes > 0; nbytes += i)
if ((i = write(pfd[0], buf + nbytes, rc - nbytes)) < 0) goto done;
}
else if (fd_bits & 1)
}
else
{
- for (nbytes = 0; rc - nbytes > 0; nbytes += i)
+ for (int nbytes = 0; rc - nbytes > 0; nbytes += i)
if ((i = tls_write(ct_ctx, buf + nbytes, rc - nbytes, FALSE)) < 0)
goto done;
}
uschar *interface, transport_instance *tblock,
BOOL *message_defer, BOOL suppress_tls)
{
-address_item *addr;
smtp_transport_options_block * ob = SOB tblock->options_block;
int yield = OK;
int save_errno;
if (continue_hostname && continue_sequence == 1)
{
- address_item * addr;
-
sx.peer_offered = smtp_peer_options;
sx.pending_MAIL = FALSE;
sx.ok = TRUE;
sx.next_addr = NULL;
- for (addr = addrlist; addr; addr = addr->next)
+ for (address_item * addr = addrlist; addr; addr = addr->next)
addr->transport_return = PENDING_OK;
}
else
case 1: sx.ok = TRUE; /* 2xx (only) => OK, but if LMTP, */
if (!sx.lmtp) sx.completed_addr = TRUE; /* can't tell about progress yet */
- case 0: break; /* No 2xx or 5xx, but no probs */
+ case 0: break; /* No 2xx or 5xx, but no probs */
- case -1: goto END_OFF; /* Timeout on RCPT */
+ case -1: goto END_OFF; /* Timeout on RCPT */
#ifdef EXPERIMENTAL_PIPE_CONNECT
+ case -5: /* TLS first-read error */
case -4: HDEBUG(D_transport)
debug_printf("failed reaping pipelined cmd responses\n");
#endif
{
case 3: sx.ok = TRUE; /* 2xx & 5xx => OK & progress made */
case 2: sx.completed_addr = TRUE; /* 5xx (only) => progress made */
- break;
+ break;
- case 1: sx.ok = TRUE; /* 2xx (only) => OK, but if LMTP, */
+ case 1: sx.ok = TRUE; /* 2xx (only) => OK, but if LMTP, */
if (!sx.lmtp) sx.completed_addr = TRUE; /* can't tell about progress yet */
- case 0: break; /* No 2xx or 5xx, but no probs */
+ case 0: break; /* No 2xx or 5xx, but no probs */
- case -1: goto END_OFF; /* Timeout on RCPT */
+ case -1: goto END_OFF; /* Timeout on RCPT */
#ifdef EXPERIMENTAL_PIPE_CONNECT
+ case -5: /* TLS first-read error */
case -4: HDEBUG(D_transport)
debug_printf("failed reaping pipelined cmd responses\n");
#endif
- default: goto RESPONSE_FAILED; /* I/O error, or any MAIL/DATA error */
+ default: goto RESPONSE_FAILED; /* I/O error, or any MAIL/DATA error */
}
}
/* Process all transported addresses - for LMTP or PRDR, read a status for
each one. */
- for (addr = addrlist; addr != sx.first_addr; addr = addr->next)
+ for (address_item * addr = addrlist; addr != sx.first_addr; addr = addr->next)
{
if (addr->transport_return != PENDING_OK) continue;
errno = ERRNO_DATA4XX;
addrlist->more_errno |= ((sx.buffer[1] - '0')*10 + sx.buffer[2] - '0') << 8;
}
- for (addr = addrlist; addr != sx.first_addr; addr = addr->next)
+ for (address_item * addr = addrlist; addr != sx.first_addr; addr = addr->next)
if (sx.buffer[0] == '5' || addr->transport_return == OK)
addr->transport_return = PENDING_OK; /* allow set_errno action */
goto RESPONSE_FAILED;
and update the journal, or setup retry. */
overall_message = string_printing(sx.buffer);
- for (addr = addrlist; addr != sx.first_addr; addr = addr->next)
+ for (address_item * addr = addrlist; addr != sx.first_addr; addr = addr->next)
if (addr->transport_return == OK)
addr->message = string_sprintf("%s\\n%s", addr->message, overall_message);
- for (addr = addrlist; addr != sx.first_addr; addr = addr->next)
+ for (address_item * addr = addrlist; addr != sx.first_addr; addr = addr->next)
if (addr->transport_return == OK)
{
if (testflag(addr, af_homonym))
operation, the old commented-out code was removed on 17-Sep-99. */
SEND_QUIT:
+#ifdef TCP_CORK
+(void) setsockopt(sx.cctx.sock, IPPROTO_TCP, TCP_CORK, US &on, sizeof(on));
+#endif
if (sx.send_quit) (void)smtp_write_command(&sx, SCMD_FLUSH, "QUIT\r\n");
END_OFF:
shutdown(sx.cctx.sock, SHUT_WR);
millisleep(f.running_in_test_harness ? 200 : 20);
if (fcntl(sx.cctx.sock, F_SETFL, O_NONBLOCK) == 0)
- for (rc = 16; read(sx.cctx.sock, sx.inbuffer, sizeof(sx.inbuffer)) > 0 && rc > 0;)
- rc--; /* drain socket */
+ for (int i = 16; read(sx.cctx.sock, sx.inbuffer, sizeof(sx.inbuffer)) > 0 && i > 0;)
+ i--; /* drain socket */
}
(void)close(sx.cctx.sock);
prepare_addresses(address_item *addrlist, host_item *host)
{
address_item *first_addr = NULL;
-address_item *addr;
-for (addr = addrlist; addr; addr = addr->next)
+for (address_item * addr = addrlist; addr; addr = addr->next)
if (addr->transport_return == DEFER)
{
if (!first_addr) first_addr = addr;
transport_instance *tblock, /* data for this instantiation */
address_item *addrlist) /* addresses we are working on */
{
-int cutoff_retry;
int defport;
int hosts_defer = 0;
int hosts_fail = 0;
int hosts_serial = 0;
int hosts_total = 0;
int total_hosts_tried = 0;
-address_item *addr;
BOOL expired = TRUE;
uschar *expanded_hosts = NULL;
uschar *pistring;
uschar *tid = string_sprintf("%s transport", tblock->name);
smtp_transport_options_block *ob = SOB tblock->options_block;
host_item *hostlist = addrlist->host_list;
-host_item *host;
+host_item *host = NULL;
DEBUG(D_transport)
{
debug_printf("%s transport entered\n", tblock->name);
- for (addr = addrlist; addr; addr = addr->next)
+ for (address_item * addr = addrlist; addr; addr = addr->next)
debug_printf(" %s\n", addr->address);
if (hostlist)
{
debug_printf("hostlist:\n");
- for (host = hostlist; host; host = host->next)
+ for (host_item * host = hostlist; host; host = host->next)
debug_printf(" '%s' IP %s port %d\n", host->name, host->address, host->port);
}
if (continue_hostname)
time. After that, set the status and error data for any addresses that haven't
had it set already. */
-for (cutoff_retry = 0;
+for (int cutoff_retry = 0;
expired && cutoff_retry < (ob->delay_after_cutoff ? 1 : 2);
cutoff_retry++)
{
{
int rc;
int host_af;
- uschar *rs;
BOOL host_is_expired = FALSE;
BOOL message_defer = FALSE;
BOOL some_deferred = FALSE;
if (!host->address)
{
int new_port, flags;
- host_item *hh;
if (host->status >= hstatus_unusable)
{
/* Update the host (and any additional blocks, resulting from
multihoming) with a host-specific port, if any. */
- for (hh = host; hh != nexthost; hh = hh->next) hh->port = new_port;
+ for (host_item * hh = host; hh != nexthost; hh = hh->next) hh->port = new_port;
/* Failure to find the host at this time (usually DNS temporary failure)
is really a kind of routing failure rather than a transport failure.
"HOST_FIND_AGAIN" : "HOST_FIND_FAILED", host->name);
host->status = hstatus_unusable;
- for (addr = addrlist; addr; addr = addr->next)
+ for (address_item * addr = addrlist; addr; addr = addr->next)
{
if (addr->transport_return != DEFER) continue;
addr->basic_errno = ERRNO_UNKNOWNHOST;
if (rc == HOST_FOUND_LOCAL && !ob->allow_localhost)
{
- for (addr = addrlist; addr; addr = addr->next)
+ for (address_item * addr = addrlist; addr; addr = addr->next)
{
addr->basic_errno = 0;
addr->message = string_sprintf("%s transport found host %s to be "
&domainlist_anchor, NULL, MCL_DOMAIN, TRUE, NULL) == OK))
{
expired = FALSE;
- for (addr = addrlist; addr; addr = addr->next)
+ for (address_item * addr = addrlist; addr; addr = addr->next)
if (addr->transport_return == DEFER)
addr->message = US"domain matches queue_smtp_domains, or -odqs set";
continue; /* With next host */
treated separately. */
host_af = Ustrchr(host->address, ':') == NULL ? AF_INET : AF_INET6;
- if ((rs = ob->interface) && *rs)
{
- if (!smtp_get_interface(rs, host_af, addrlist, &interface, tid))
- return FALSE;
- pistring = string_sprintf("%s/%s", pistring, interface);
+ uschar * s = ob->interface;
+ if (s && *s)
+ {
+ if (!smtp_get_interface(s, host_af, addrlist, &interface, tid))
+ return FALSE;
+ pistring = string_sprintf("%s/%s", pistring, interface);
+ }
}
/* The first time round the outer loop, check the status of the host by
if (f.dont_deliver)
{
- host_item *host2;
set_errno_nohost(addrlist, 0, NULL, OK, FALSE);
- for (addr = addrlist; addr; addr = addr->next)
+ for (address_item * addr = addrlist; addr; addr = addr->next)
{
addr->host_used = host;
addr->special_action = '*';
{
debug_printf("*** delivery by %s transport bypassed by -N option\n"
"*** host and remaining hosts:\n", tblock->name);
- for (host2 = host; host2; host2 = host2->next)
+ for (host_item * host2 = host; host2; host2 = host2->next)
debug_printf(" %s [%s]\n", host2->name,
host2->address ? host2->address : US"unset");
}
if (!host_is_expired && ++unexpired_hosts_tried >= ob->hosts_max_try)
{
- host_item *h;
DEBUG(D_transport)
debug_printf("hosts_max_try limit reached with this host\n");
- for (h = host; h; h = h->next) if (h->mx != host->mx)
+ for (host_item * h = host; h; h = h->next) if (h->mx != host->mx)
{
nexthost = h;
unexpired_hosts_tried--;
/* Delivery attempt finished */
- rs = rc == OK ? US"OK"
- : rc == DEFER ? US"DEFER"
- : rc == ERROR ? US"ERROR"
- : US"?";
-
set_process_info("delivering %s: just tried %s [%s]%s for %s%s: result %s",
message_id, host->name, host->address, pistring, addrlist->address,
- addrlist->next ? " (& others)" : "", rs);
+ addrlist->next ? " (& others)" : "", rc_to_string(rc));
/* Release serialization if set up */
case, see if any of them are deferred. */
if (rc == OK)
- for (addr = addrlist; addr; addr = addr->next)
+ for (address_item * addr = addrlist; addr; addr = addr->next)
if (addr->transport_return == DEFER)
{
some_deferred = TRUE;
if (mua_wrapper)
{
- for (addr = addrlist; addr; addr = addr->next)
+ for (address_item * addr = addrlist; addr; addr = addr->next)
addr->transport_return = FAIL;
goto END_TRANSPORT;
}
down an existing TCP/IP connection, and something caused the host not to be
found, we end up here, but can detect these cases and handle them specially. */
-for (addr = addrlist; addr; addr = addr->next)
+for (address_item * addr = addrlist; addr; addr = addr->next)
{
/* If host is not NULL, it means that we stopped processing the host list
because of hosts_max_try or hosts_max_try_hardlimit. In the former case, this