void tls_session_information(tls_session_t *tls_session)
{
	char const *str_write_p, *str_version, *str_content_type = "";
	char const *str_details1 = "", *str_details2= "";
	REQUEST *request;
	char buffer[32];

	/*
	 *	Don't print this out in the normal course of
	 *	operations.
	 */
	if (rad_debug_lvl == 0) {
		return;
	}

	str_write_p = tls_session->info.origin ? ">>>" : "<<<";

	switch (tls_session->info.version) {
	case SSL2_VERSION:
		str_version = "SSL 2.0 ";
		break;
	case SSL3_VERSION:
		str_version = "SSL 3.0 ";
		break;
	case TLS1_VERSION:
		str_version = "TLS 1.0 ";
		break;
#ifdef TLS1_1_VERSION
	case TLS1_1_VERSION:
		str_version = "TLS 1.1 ";
		break;
#endif
#ifdef TLS1_2_VERSION
	case TLS1_2_VERSION:
		str_version = "TLS 1.2 ";
		break;
#endif
#ifdef TLS1_3_VERSON
	case TLS1_3_VERSION:
		str_version = "TLS 1.3 ";
		break;
#endif

	default:
		sprintf(buffer, "UNKNOWN TLS VERSION ?%04X?", tls_session->info.version);
		str_version = buffer;
		break;
	}

	if (tls_session->info.version == SSL3_VERSION ||
	    tls_session->info.version == TLS1_VERSION) {
		switch (tls_session->info.content_type) {
		case SSL3_RT_CHANGE_CIPHER_SPEC:
			str_content_type = "ChangeCipherSpec";
			break;

		case SSL3_RT_ALERT:
			str_content_type = "Alert";
			break;

		case SSL3_RT_HANDSHAKE:
			str_content_type = "Handshake";
			break;

		case SSL3_RT_APPLICATION_DATA:
			str_content_type = "ApplicationData";
			break;

		default:
			str_content_type = "UnknownContentType";
			break;
		}

		if (tls_session->info.content_type == SSL3_RT_ALERT) {
			str_details1 = ", ???";

			if (tls_session->info.record_len == 2) {

				switch (tls_session->info.alert_level) {
				case SSL3_AL_WARNING:
					str_details1 = ", warning";
					break;
				case SSL3_AL_FATAL:
					str_details1 = ", fatal";
					break;
				}

				str_details2 = " ???";
				switch (tls_session->info.alert_description) {
				case SSL3_AD_CLOSE_NOTIFY:
					str_details2 = " close_notify";
					break;

				case SSL3_AD_UNEXPECTED_MESSAGE:
					str_details2 = " unexpected_message";
					break;

				case SSL3_AD_BAD_RECORD_MAC:
					str_details2 = " bad_record_mac";
					break;

				case TLS1_AD_DECRYPTION_FAILED:
					str_details2 = " decryption_failed";
					break;

				case TLS1_AD_RECORD_OVERFLOW:
					str_details2 = " record_overflow";
					break;

				case SSL3_AD_DECOMPRESSION_FAILURE:
					str_details2 = " decompression_failure";
					break;

				case SSL3_AD_HANDSHAKE_FAILURE:
					str_details2 = " handshake_failure";
					break;

				case SSL3_AD_BAD_CERTIFICATE:
					str_details2 = " bad_certificate";
					break;

				case SSL3_AD_UNSUPPORTED_CERTIFICATE:
					str_details2 = " unsupported_certificate";
					break;

				case SSL3_AD_CERTIFICATE_REVOKED:
					str_details2 = " certificate_revoked";
					break;

				case SSL3_AD_CERTIFICATE_EXPIRED:
					str_details2 = " certificate_expired";
					break;

				case SSL3_AD_CERTIFICATE_UNKNOWN:
					str_details2 = " certificate_unknown";
					break;

				case SSL3_AD_ILLEGAL_PARAMETER:
					str_details2 = " illegal_parameter";
					break;

				case TLS1_AD_UNKNOWN_CA:
					str_details2 = " unknown_ca";
					break;

				case TLS1_AD_ACCESS_DENIED:
					str_details2 = " access_denied";
					break;

				case TLS1_AD_DECODE_ERROR:
					str_details2 = " decode_error";
					break;

				case TLS1_AD_DECRYPT_ERROR:
					str_details2 = " decrypt_error";
					break;

				case TLS1_AD_EXPORT_RESTRICTION:
					str_details2 = " export_restriction";
					break;

				case TLS1_AD_PROTOCOL_VERSION:
					str_details2 = " protocol_version";
					break;

				case TLS1_AD_INSUFFICIENT_SECURITY:
					str_details2 = " insufficient_security";
					break;

				case TLS1_AD_INTERNAL_ERROR:
					str_details2 = " internal_error";
					break;

				case TLS1_AD_USER_CANCELLED:
					str_details2 = " user_canceled";
					break;

				case TLS1_AD_NO_RENEGOTIATION:
					str_details2 = " no_renegotiation";
					break;
				}
			}
		}

		if (tls_session->info.content_type == SSL3_RT_HANDSHAKE) {
			str_details1 = "???";

			if (tls_session->info.record_len > 0) switch (tls_session->info.handshake_type) {
			case SSL3_MT_HELLO_REQUEST:
				str_details1 = ", HelloRequest";
				break;

			case SSL3_MT_CLIENT_HELLO:
				str_details1 = ", ClientHello";
				break;

			case SSL3_MT_SERVER_HELLO:
				str_details1 = ", ServerHello";
				break;

			case SSL3_MT_CERTIFICATE:
				str_details1 = ", Certificate";
				break;

			case SSL3_MT_SERVER_KEY_EXCHANGE:
				str_details1 = ", ServerKeyExchange";
				break;

			case SSL3_MT_CERTIFICATE_REQUEST:
				str_details1 = ", CertificateRequest";
				break;

			case SSL3_MT_SERVER_DONE:
				str_details1 = ", ServerHelloDone";
				break;

			case SSL3_MT_CERTIFICATE_VERIFY:
				str_details1 = ", CertificateVerify";
				break;

			case SSL3_MT_CLIENT_KEY_EXCHANGE:
				str_details1 = ", ClientKeyExchange";
				break;

			case SSL3_MT_FINISHED:
				str_details1 = ", Finished";
				break;
			}
		}
	}

	snprintf(tls_session->info.info_description,
		 sizeof(tls_session->info.info_description),
		 "%s %s%s [length %04lx]%s%s\n",
		 str_write_p, str_version, str_content_type,
		 (unsigned long)tls_session->info.record_len,
		 str_details1, str_details2);

	request = SSL_get_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_REQUEST);
	if (request) {
		RDEBUG2("%s", tls_session->info.info_description);
	} else {
		DEBUG2("%s", tls_session->info.info_description);
	}
}