wolfio: dtls: retry instead of returning WANT_READ on different peer

If EmbedReceiveFrom() returns WANT_READ, a blocking socket will not know how to
deal with the error. Retry the recvfrom instead adjusting the timeout.
This commit is contained in:
Marco Oliverio
2023-02-14 14:03:37 +00:00
parent 5f293bf736
commit 73f502e189

View File

@@ -51,6 +51,14 @@ Possible IO enable options:
* HAVE_HTTP_CLIENT: Enables HTTP client API's default: off * HAVE_HTTP_CLIENT: Enables HTTP client API's default: off
(unless HAVE_OCSP or HAVE_CRL_IO defined) (unless HAVE_OCSP or HAVE_CRL_IO defined)
* HAVE_IO_TIMEOUT: Enables support for connect timeout default: off * HAVE_IO_TIMEOUT: Enables support for connect timeout default: off
*
* DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER: This flag has effect only if
* ASN_NO_TIME is enabled. If enabled invalid peers messages are ignored
* indefinetely. If not enabled EmbedReceiveFrom will return timeout after
* DTLS_RECEIVEFROM_MAX_INVALID_PEER number of packets from invalid peers. When
* enabled, without a timer, EmbedReceivefrom can't check if the timeout is
* expired and it may never return under a continous flow of invalid packets.
* default: off
*/ */
@@ -59,6 +67,11 @@ Possible IO enable options:
but they'll still need SetCallback xxx() at end of file but they'll still need SetCallback xxx() at end of file
*/ */
#if defined(NO_ASN_TIME) && !defined(DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER) \
&& !defined(DTLS_RECEIVEFROM_MAX_INVALID_PEER)
#define DTLS_RECEIVEFROM_MAX_INVALID_PEER 10
#endif
#if defined(USE_WOLFSSL_IO) || defined(HAVE_HTTP_CLIENT) #if defined(USE_WOLFSSL_IO) || defined(HAVE_HTTP_CLIENT)
/* Translates return codes returned from /* Translates return codes returned from
@@ -400,6 +413,11 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
SOCKADDR_S lclPeer; SOCKADDR_S lclPeer;
SOCKADDR_S* peer; SOCKADDR_S* peer;
XSOCKLENT peerSz = 0; XSOCKLENT peerSz = 0;
#ifndef NO_ASN_TIME
word32 start = 0;
#elif !defined(DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER)
word32 invalidPeerPackets = 0;
#endif
WOLFSSL_ENTER("EmbedReceiveFrom"); WOLFSSL_ENTER("EmbedReceiveFrom");
@@ -438,8 +456,24 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
} }
#endif /* WOLFSSL_DTLS13 */ #endif /* WOLFSSL_DTLS13 */
if (!doDtlsTimeout) do {
if (!doDtlsTimeout) {
dtls_timeout = 0; dtls_timeout = 0;
}
else {
#ifndef NO_ASN_TIME
if (start == 0) {
start = LowResTimer();
}
else {
dtls_timeout -= LowResTimer() - start;
start = LowResTimer();
if (dtls_timeout < 0 || dtls_timeout > DTLS_TIMEOUT_MAX)
return WOLFSSL_CBIO_ERR_TIMEOUT;
}
#endif
}
if (!wolfSSL_get_using_nonblock(ssl)) { if (!wolfSSL_get_using_nonblock(ssl)) {
#ifdef USE_WINDOWS_API #ifdef USE_WINDOWS_API
@@ -472,7 +506,8 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
#ifndef NO_ASN_TIME #ifndef NO_ASN_TIME
else if (IsSCR(ssl)) { else if (IsSCR(ssl)) {
if (ssl->dtls_start_timeout && if (ssl->dtls_start_timeout &&
LowResTimer() - ssl->dtls_start_timeout > (word32)dtls_timeout) { LowResTimer() - ssl->dtls_start_timeout >
(word32)dtls_timeout) {
ssl->dtls_start_timeout = 0; ssl->dtls_start_timeout = 0;
return WOLFSSL_CBIO_ERR_TIMEOUT; return WOLFSSL_CBIO_ERR_TIMEOUT;
} }
@@ -486,9 +521,9 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
(SOCKADDR*)peer, peer != NULL ? &peerSz : NULL); (SOCKADDR*)peer, peer != NULL ? &peerSz : NULL);
/* From the RECV(2) man page /* From the RECV(2) man page
* The returned address is truncated if the buffer provided is too small; in * The returned address is truncated if the buffer provided is too
* this case, addrlen will return a value greater than was supplied to the * small; in this case, addrlen will return a value greater than was
* call. * supplied to the call.
*/ */
if (dtlsCtx->connected) { if (dtlsCtx->connected) {
/* No need to sanitize the value of peerSz */ /* No need to sanitize the value of peerSz */
@@ -522,6 +557,7 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
} }
else { else {
WOLFSSL_MSG("Ignoring 0-length datagram"); WOLFSSL_MSG("Ignoring 0-length datagram");
continue;
} }
return recvd; return recvd;
} }
@@ -535,7 +571,17 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
!sockAddrEqual(peer, peerSz, (SOCKADDR_S*)dtlsCtx->peer.sa, !sockAddrEqual(peer, peerSz, (SOCKADDR_S*)dtlsCtx->peer.sa,
dtlsCtx->peer.sz))) { dtlsCtx->peer.sz))) {
WOLFSSL_MSG(" Ignored packet from invalid peer"); WOLFSSL_MSG(" Ignored packet from invalid peer");
return WOLFSSL_CBIO_ERR_WANT_READ; #if defined(NO_ASN_TIME) && \
!defined(DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER)
if (doDtlsTimeout) {
invalidPeerPackets++;
if (invalidPeerPackets > DTLS_RECEIVEFROM_MAX_INVALID_PEER)
return wolfSSL_dtls_get_using_nonblock(ssl)
? WOLFSSL_CBIO_ERR_WANT_READ
: WOLFSSL_CBIO_ERR_TIMEOUT;
}
#endif /* NO_ASN_TIME && !DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER */
continue;
} }
} }
else { else {
@@ -545,6 +591,8 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
#ifndef NO_ASN_TIME #ifndef NO_ASN_TIME
ssl->dtls_start_timeout = 0; ssl->dtls_start_timeout = 0;
#endif /* !NO_ASN_TIME */ #endif /* !NO_ASN_TIME */
break;
} while (1);
return recvd; return recvd;
} }