diff --git a/src/internal.c b/src/internal.c index e6fa862be4..8ccfa9ce69 100644 --- a/src/internal.c +++ b/src/internal.c @@ -7945,7 +7945,8 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) ssl->buffers.dtlsCtx.rfd = -1; ssl->buffers.dtlsCtx.wfd = -1; - ssl->buffers.dtlsCtx.isDGramCached = 0; + ssl->buffers.dtlsCtx.rfdIsDGram = 0; + ssl->buffers.dtlsCtx.wfdIsDGram = 0; #ifdef WOLFSSL_RW_THREADED if (wc_InitRwLock(&ssl->buffers.dtlsCtx.peerLock) != 0) diff --git a/src/ssl.c b/src/ssl.c index 26bbf83373..ade8e5cfa3 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -1131,7 +1131,10 @@ int wolfSSL_set_read_fd(WOLFSSL* ssl, int fd) if (ssl->options.dtls) { ssl->IOCB_ReadCtx = &ssl->buffers.dtlsCtx; ssl->buffers.dtlsCtx.rfd = fd; - ssl->buffers.dtlsCtx.isDGramCached = 0; + #ifdef USE_WOLFSSL_IO + ssl->buffers.dtlsCtx.rfdIsDGram = + (byte)(wolfIO_SockIsDGram(fd) != 0); + #endif } #endif @@ -1156,7 +1159,10 @@ int wolfSSL_set_write_fd(WOLFSSL* ssl, int fd) if (ssl->options.dtls) { ssl->IOCB_WriteCtx = &ssl->buffers.dtlsCtx; ssl->buffers.dtlsCtx.wfd = fd; - ssl->buffers.dtlsCtx.isDGramCached = 0; + #ifdef USE_WOLFSSL_IO + ssl->buffers.dtlsCtx.wfdIsDGram = + (byte)(wolfIO_SockIsDGram(fd) != 0); + #endif } #endif @@ -6821,7 +6827,10 @@ int wolfSSL_set_compression(WOLFSSL* ssl) if (ssl->options.dtls) { ssl->IOCB_ReadCtx = &ssl->buffers.dtlsCtx; ssl->buffers.dtlsCtx.rfd = rfd; - ssl->buffers.dtlsCtx.isDGramCached = 0; + #ifdef USE_WOLFSSL_IO + ssl->buffers.dtlsCtx.rfdIsDGram = + (byte)(wolfIO_SockIsDGram(rfd) != 0); + #endif } #endif diff --git a/src/wolfio.c b/src/wolfio.c index d3be03c425..c99df69560 100644 --- a/src/wolfio.c +++ b/src/wolfio.c @@ -643,27 +643,22 @@ static int PeerIsIpv6(const SOCKADDR_S *peer, XSOCKLENT len) #endif /* !WOLFSSL_IPV6 */ /* Return non-zero iff sfd is a SOCK_DGRAM socket. A descriptor's type is - * fixed for its lifetime, so the getsockopt(SO_TYPE) probe runs once per - * connection and is cached in dtlsCtx; the cache is invalidated wherever - * rfd/wfd is reassigned. */ -static int isDGramSock(WOLFSSL_DTLS_CTX* dtlsCtx, int sfd) + * fixed for its lifetime, so the probe runs where dtlsCtx.rfd/wfd is + * assigned and the result is stored alongside the descriptor, keeping the + * getsockopt() syscall out of the I/O callbacks. */ +int wolfIO_SockIsDGram(int sfd) { int type = 0; /* optvalue 'type' is of size int */ XSOCKLENT length = (XSOCKLENT)sizeof(type); - if (dtlsCtx->isDGramCached) - return dtlsCtx->isDGram; - if (getsockopt(sfd, SOL_SOCKET, SO_TYPE, (XSOCKOPT_TYPE_OPTVAL_TYPE)&type, &length) == 0 && type != SOCK_DGRAM) { - dtlsCtx->isDGram = 0; + return 0; } else { - dtlsCtx->isDGram = 1; + return 1; } - dtlsCtx->isDGramCached = 1; - return dtlsCtx->isDGram; } void wolfSSL_SetRecvFrom(WOLFSSL* ssl, WolfSSLRecvFrom recvFrom) @@ -853,7 +848,7 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx) return recvd; } else if (recvd == 0) { - if (!isDGramSock(dtlsCtx, sd)) { + if (!dtlsCtx->rfdIsDGram) { /* Closed TCP connection */ recvd = WOLFSSL_CBIO_ERR_CONN_CLOSE; } @@ -951,7 +946,7 @@ int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx) if (sz < 0) return WOLFSSL_CBIO_ERR_GENERAL; - if (!isDGramSock(dtlsCtx, sd)) { + if (!dtlsCtx->wfdIsDGram) { /* Probably a TCP socket. peer and peerSz MUST be NULL and 0 */ } else if (!dtlsCtx->connected) { diff --git a/tests/api/test_dtls.c b/tests/api/test_dtls.c index e17b33e838..f160cdc594 100644 --- a/tests/api/test_dtls.c +++ b/tests/api/test_dtls.c @@ -3613,10 +3613,6 @@ static word32 test_wolfSSL_dtls_stateless_HashWOLFSSL(const WOLFSSL* ssl) sslCopy.dtls13FastTimeout = 0; #endif sslCopy.keys.dtls_peer_handshake_number = 0; - /* isDGram* is a local-socket-type memoization the IO callbacks may - * populate lazily; it is not peer state and not relevant here. */ - sslCopy.buffers.dtlsCtx.isDGramCached = 0; - sslCopy.buffers.dtlsCtx.isDGram = 0; XMEMSET(&sslCopy.alert_history, 0, sizeof(sslCopy.alert_history)); sslCopy.hsHashes = NULL; #if !defined(WOLFSSL_NO_CLIENT_AUTH) && \ diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 8dac598040..66c432f408 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -2791,10 +2791,11 @@ typedef struct WOLFSSL_DTLS_CTX { * connected (connect() and bind() both called). * This means that sendto and recvfrom do not need to * specify and store the peer address. */ - byte isDGramCached:1; /* whether isDGram below is valid; reset whenever - * rfd/wfd is (re)assigned so the SO_TYPE probe - * re-runs once for the new descriptor. */ - byte isDGram:1; /* cached isDGramSock() for the rfd/wfd socket */ + byte rfdIsDGram:1; /* whether rfd is a SOCK_DGRAM socket; probed with + * getsockopt(SO_TYPE) where rfd is assigned to keep + * the syscall out of the I/O callbacks. */ + byte wfdIsDGram:1; /* as rfdIsDGram, for wfd; rfd and wfd may be + * different sockets of different types. */ #ifdef WOLFSSL_DTLS_CID byte processingPendingRecord:1; #endif diff --git a/wolfssl/wolfio.h b/wolfssl/wolfio.h index eb609235d7..fc306ea6ab 100644 --- a/wolfssl/wolfio.h +++ b/wolfssl/wolfio.h @@ -703,6 +703,7 @@ WOLFSSL_LOCAL int SslBioReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx); WOLFSSL_API int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx); WOLFSSL_API int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx); + WOLFSSL_LOCAL int wolfIO_SockIsDGram(int sfd); #ifdef WOLFSSL_MULTICAST WOLFSSL_API int EmbedReceiveFromMcast(WOLFSSL *ssl, char *buf, int sz, void *ctx);