Skip to content

Commit 73f502e

Browse files
committed
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.
1 parent 5f293bf commit 73f502e

1 file changed

Lines changed: 117 additions & 69 deletions

File tree

src/wolfio.c

Lines changed: 117 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,14 @@ Possible IO enable options:
5151
* HAVE_HTTP_CLIENT: Enables HTTP client API's default: off
5252
(unless HAVE_OCSP or HAVE_CRL_IO defined)
5353
* HAVE_IO_TIMEOUT: Enables support for connect timeout default: off
54+
*
55+
* DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER: This flag has effect only if
56+
* ASN_NO_TIME is enabled. If enabled invalid peers messages are ignored
57+
* indefinetely. If not enabled EmbedReceiveFrom will return timeout after
58+
* DTLS_RECEIVEFROM_MAX_INVALID_PEER number of packets from invalid peers. When
59+
* enabled, without a timer, EmbedReceivefrom can't check if the timeout is
60+
* expired and it may never return under a continous flow of invalid packets.
61+
* default: off
5462
*/
5563

5664

@@ -59,6 +67,11 @@ Possible IO enable options:
5967
but they'll still need SetCallback xxx() at end of file
6068
*/
6169

70+
#if defined(NO_ASN_TIME) && !defined(DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER) \
71+
&& !defined(DTLS_RECEIVEFROM_MAX_INVALID_PEER)
72+
#define DTLS_RECEIVEFROM_MAX_INVALID_PEER 10
73+
#endif
74+
6275
#if defined(USE_WOLFSSL_IO) || defined(HAVE_HTTP_CLIENT)
6376

6477
/* Translates return codes returned from
@@ -400,6 +413,11 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
400413
SOCKADDR_S lclPeer;
401414
SOCKADDR_S* peer;
402415
XSOCKLENT peerSz = 0;
416+
#ifndef NO_ASN_TIME
417+
word32 start = 0;
418+
#elif !defined(DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER)
419+
word32 invalidPeerPackets = 0;
420+
#endif
403421

404422
WOLFSSL_ENTER("EmbedReceiveFrom");
405423

@@ -438,10 +456,26 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
438456
}
439457
#endif /* WOLFSSL_DTLS13 */
440458

441-
if (!doDtlsTimeout)
442-
dtls_timeout = 0;
459+
do {
460+
461+
if (!doDtlsTimeout) {
462+
dtls_timeout = 0;
463+
}
464+
else {
465+
#ifndef NO_ASN_TIME
466+
if (start == 0) {
467+
start = LowResTimer();
468+
}
469+
else {
470+
dtls_timeout -= LowResTimer() - start;
471+
start = LowResTimer();
472+
if (dtls_timeout < 0 || dtls_timeout > DTLS_TIMEOUT_MAX)
473+
return WOLFSSL_CBIO_ERR_TIMEOUT;
474+
}
475+
#endif
476+
}
443477

444-
if (!wolfSSL_get_using_nonblock(ssl)) {
478+
if (!wolfSSL_get_using_nonblock(ssl)) {
445479
#ifdef USE_WINDOWS_API
446480
DWORD timeout = dtls_timeout * 1000;
447481
#ifdef WOLFSSL_DTLS13
@@ -464,87 +498,101 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
464498
#endif /* WOLFSSL_DTLS13 */
465499
timeout.tv_sec = dtls_timeout;
466500
#endif
467-
if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
468-
sizeof(timeout)) != 0) {
501+
if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
502+
sizeof(timeout)) != 0) {
469503
WOLFSSL_MSG("setsockopt rcvtimeo failed");
504+
}
470505
}
471-
}
472506
#ifndef NO_ASN_TIME
473-
else if(IsSCR(ssl)) {
474-
if (ssl->dtls_start_timeout &&
475-
LowResTimer() - ssl->dtls_start_timeout > (word32)dtls_timeout) {
476-
ssl->dtls_start_timeout = 0;
477-
return WOLFSSL_CBIO_ERR_TIMEOUT;
478-
}
479-
else if (!ssl->dtls_start_timeout) {
480-
ssl->dtls_start_timeout = LowResTimer();
507+
else if (IsSCR(ssl)) {
508+
if (ssl->dtls_start_timeout &&
509+
LowResTimer() - ssl->dtls_start_timeout >
510+
(word32)dtls_timeout) {
511+
ssl->dtls_start_timeout = 0;
512+
return WOLFSSL_CBIO_ERR_TIMEOUT;
513+
}
514+
else if (!ssl->dtls_start_timeout) {
515+
ssl->dtls_start_timeout = LowResTimer();
516+
}
481517
}
482-
}
483518
#endif /* !NO_ASN_TIME */
484519

485-
recvd = (int)DTLS_RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags,
486-
(SOCKADDR*)peer, peer != NULL ? &peerSz : NULL);
520+
recvd = (int)DTLS_RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags,
521+
(SOCKADDR*)peer, peer != NULL ? &peerSz : NULL);
487522

488-
/* From the RECV(2) man page
489-
* The returned address is truncated if the buffer provided is too small; in
490-
* this case, addrlen will return a value greater than was supplied to the
491-
* call.
492-
*/
493-
if (dtlsCtx->connected) {
494-
/* No need to sanitize the value of peerSz */
495-
}
496-
else if (dtlsCtx->userSet) {
497-
/* Truncate peer size */
498-
if (peerSz > (XSOCKLENT)sizeof(lclPeer))
499-
peerSz = (XSOCKLENT)sizeof(lclPeer);
500-
}
501-
else {
502-
/* Truncate peer size */
503-
if (peerSz > (XSOCKLENT)dtlsCtx->peer.bufSz)
504-
peerSz = (XSOCKLENT)dtlsCtx->peer.bufSz;
505-
}
523+
/* From the RECV(2) man page
524+
* The returned address is truncated if the buffer provided is too
525+
* small; in this case, addrlen will return a value greater than was
526+
* supplied to the call.
527+
*/
528+
if (dtlsCtx->connected) {
529+
/* No need to sanitize the value of peerSz */
530+
}
531+
else if (dtlsCtx->userSet) {
532+
/* Truncate peer size */
533+
if (peerSz > (XSOCKLENT)sizeof(lclPeer))
534+
peerSz = (XSOCKLENT)sizeof(lclPeer);
535+
}
536+
else {
537+
/* Truncate peer size */
538+
if (peerSz > (XSOCKLENT)dtlsCtx->peer.bufSz)
539+
peerSz = (XSOCKLENT)dtlsCtx->peer.bufSz;
540+
}
506541

507-
recvd = TranslateReturnCode(recvd, sd);
542+
recvd = TranslateReturnCode(recvd, sd);
508543

509-
if (recvd < 0) {
510-
WOLFSSL_MSG("Embed Receive From error");
511-
recvd = TranslateIoError(recvd);
512-
if (recvd == WOLFSSL_CBIO_ERR_WANT_READ &&
513-
!wolfSSL_dtls_get_using_nonblock(ssl)) {
514-
recvd = WOLFSSL_CBIO_ERR_TIMEOUT;
544+
if (recvd < 0) {
545+
WOLFSSL_MSG("Embed Receive From error");
546+
recvd = TranslateIoError(recvd);
547+
if (recvd == WOLFSSL_CBIO_ERR_WANT_READ &&
548+
!wolfSSL_dtls_get_using_nonblock(ssl)) {
549+
recvd = WOLFSSL_CBIO_ERR_TIMEOUT;
550+
}
551+
return recvd;
515552
}
516-
return recvd;
517-
}
518-
else if (recvd == 0) {
519-
if (!isDGramSock(sd)) {
520-
/* Closed TCP connection */
521-
recvd = WOLFSSL_CBIO_ERR_CONN_CLOSE;
553+
else if (recvd == 0) {
554+
if (!isDGramSock(sd)) {
555+
/* Closed TCP connection */
556+
recvd = WOLFSSL_CBIO_ERR_CONN_CLOSE;
557+
}
558+
else {
559+
WOLFSSL_MSG("Ignoring 0-length datagram");
560+
continue;
561+
}
562+
return recvd;
522563
}
523-
else {
524-
WOLFSSL_MSG("Ignoring 0-length datagram");
564+
else if (dtlsCtx->connected) {
565+
/* Nothing to do */
566+
}
567+
else if (dtlsCtx->userSet) {
568+
/* Check we received the packet from the correct peer */
569+
if (dtlsCtx->peer.sz > 0 &&
570+
(peerSz != (XSOCKLENT)dtlsCtx->peer.sz ||
571+
!sockAddrEqual(peer, peerSz, (SOCKADDR_S*)dtlsCtx->peer.sa,
572+
dtlsCtx->peer.sz))) {
573+
WOLFSSL_MSG(" Ignored packet from invalid peer");
574+
#if defined(NO_ASN_TIME) && \
575+
!defined(DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER)
576+
if (doDtlsTimeout) {
577+
invalidPeerPackets++;
578+
if (invalidPeerPackets > DTLS_RECEIVEFROM_MAX_INVALID_PEER)
579+
return wolfSSL_dtls_get_using_nonblock(ssl)
580+
? WOLFSSL_CBIO_ERR_WANT_READ
581+
: WOLFSSL_CBIO_ERR_TIMEOUT;
582+
}
583+
#endif /* NO_ASN_TIME && !DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER */
584+
continue;
585+
}
525586
}
526-
return recvd;
527-
}
528-
else if (dtlsCtx->connected) {
529-
/* Nothing to do */
530-
}
531-
else if (dtlsCtx->userSet) {
532-
/* Check we received the packet from the correct peer */
533-
if (dtlsCtx->peer.sz > 0 &&
534-
(peerSz != (XSOCKLENT)dtlsCtx->peer.sz ||
535-
!sockAddrEqual(peer, peerSz, (SOCKADDR_S*)dtlsCtx->peer.sa,
536-
dtlsCtx->peer.sz))) {
537-
WOLFSSL_MSG(" Ignored packet from invalid peer");
538-
return WOLFSSL_CBIO_ERR_WANT_READ;
587+
else {
588+
/* Store size of saved address */
589+
dtlsCtx->peer.sz = peerSz;
539590
}
540-
}
541-
else {
542-
/* Store size of saved address */
543-
dtlsCtx->peer.sz = peerSz;
544-
}
545591
#ifndef NO_ASN_TIME
546-
ssl->dtls_start_timeout = 0;
592+
ssl->dtls_start_timeout = 0;
547593
#endif /* !NO_ASN_TIME */
594+
break;
595+
} while (1);
548596

549597
return recvd;
550598
}

0 commit comments

Comments
 (0)