diff options
author | Iwan Timmer <irtimmer@gmail.com> | 2018-07-26 21:34:16 +0200 |
---|---|---|
committer | Iwan Timmer <irtimmer@gmail.com> | 2018-07-27 22:23:17 +0200 |
commit | ba6aaf572774a49ec2ece32fff492ed814d60922 (patch) | |
tree | cf92451a203fb025860c8204360e1176bab708c3 /src/resolve/resolved-dnstls-gnutls.c | |
parent | resolved: refactor GnuTLS specific code in separate source file (diff) | |
download | systemd-ba6aaf572774a49ec2ece32fff492ed814d60922.tar.xz systemd-ba6aaf572774a49ec2ece32fff492ed814d60922.zip |
resolved: set io events after receiving EAGAIN for TLS
During handshake and TLS session closing, messages needs to be exchanged. Therefore this patch overrides the requested IO events for the TCP stream when the TLS is waiting for sending or receiving of messages during theses periods. This fixes issues with correctly closing the TLS stream and prevents the handshake from hanging in rare cases (not seen yet).
Diffstat (limited to 'src/resolve/resolved-dnstls-gnutls.c')
-rw-r--r-- | src/resolve/resolved-dnstls-gnutls.c | 13 |
1 files changed, 9 insertions, 4 deletions
diff --git a/src/resolve/resolved-dnstls-gnutls.c b/src/resolve/resolved-dnstls-gnutls.c index 9c348cef67..36ee570b46 100644 --- a/src/resolve/resolved-dnstls-gnutls.c +++ b/src/resolve/resolved-dnstls-gnutls.c @@ -86,23 +86,28 @@ int dnstls_stream_on_io(DnsStream *stream) { if (stream->dnstls_data.shutdown) { r = gnutls_bye(stream->dnstls_data.session, GNUTLS_SHUT_RDWR); - if (r == GNUTLS_E_AGAIN) + if (r == GNUTLS_E_AGAIN) { + stream->dnstls_events = gnutls_record_get_direction(stream->dnstls_data.session) == 1 ? EPOLLOUT : EPOLLIN; return -EAGAIN; - else if (r < 0) + } else if (r < 0) log_debug("Failed to invoke gnutls_bye: %s", gnutls_strerror(r)); + stream->dnstls_events = 0; stream->dnstls_data.shutdown = false; dns_stream_unref(stream); return DNSTLS_STREAM_CLOSED; } else if (stream->dnstls_data.handshake < 0) { stream->dnstls_data.handshake = gnutls_handshake(stream->dnstls_data.session); - if (stream->dnstls_data.handshake == GNUTLS_E_AGAIN) + if (stream->dnstls_data.handshake == GNUTLS_E_AGAIN) { + stream->dnstls_events = gnutls_record_get_direction(stream->dnstls_data.session) == 1 ? EPOLLOUT : EPOLLIN; return -EAGAIN; - else if (stream->dnstls_data.handshake < 0) { + } else if (stream->dnstls_data.handshake < 0) { log_debug("Failed to invoke gnutls_handshake: %s", gnutls_strerror(stream->dnstls_data.handshake)); if (gnutls_error_is_fatal(stream->dnstls_data.handshake)) return -ECONNREFUSED; } + + stream->dnstls_events = 0; } return 0; |