+/*************************************************
+* Handle TLS error *
+*************************************************/
+
+/* Called from lots of places when errors occur before actually starting to do
+the TLS handshake, that is, while the session is still in clear. Always returns
+DEFER for a server and FAIL for a client so that most calls can use "return
+tls_error(...)" to do this processing and then give an appropriate return. A
+single function is used for both server and client, because it is called from
+some shared functions.
+
+Argument:
+ prefix text to include in the logged error
+ msg additional error string (may be NULL)
+ usually obtained from gnutls_strerror()
+ host NULL if setting up a server;
+ the connected host if setting up a client
+ errstr pointer to returned error string
+
+Returns: DEFER/FAIL
+*/
+
+static int
+tls_error(const uschar *prefix, const uschar *msg, const host_item *host,
+ uschar ** errstr)
+{
+if (errstr)
+ *errstr = string_sprintf("(%s)%s%s", prefix, msg ? ": " : "", msg ? msg : US"");
+return host ? FAIL : DEFER;
+}
+
+
+/* Returns: DEFER/FAIL */
+static int
+tls_error_gnu(exim_gnutls_state_st * state, const uschar *prefix, int err,
+ uschar ** errstr)
+{
+return tls_error(prefix,
+ state && err == GNUTLS_E_FATAL_ALERT_RECEIVED
+ ? string_sprintf("rxd alert: %s",
+ US gnutls_alert_get_name(gnutls_alert_get(state->session)))
+ : US gnutls_strerror(err),
+ state ? state->host : NULL,
+ errstr);
+}
+
+static int
+tls_error_sys(const uschar *prefix, int err, const host_item *host,
+ uschar ** errstr)
+{
+return tls_error(prefix, US strerror(err), host, errstr);
+}
+
+