@@ -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
@@ -333,7 +346,7 @@ static int sockAddrEqual(
333346 if (a -> ss_family != b -> ss_family )
334347 return 0 ;
335348
336- if (a -> ss_family == AF_INET ) {
349+ if (a -> ss_family == WOLFSSL_IP4 ) {
337350
338351 if (aLen < (XSOCKLENT )sizeof (SOCKADDR_IN ))
339352 return 0 ;
@@ -349,7 +362,7 @@ static int sockAddrEqual(
349362 }
350363
351364#ifdef WOLFSSL_IPV6
352- if (a -> ss_family == AF_INET6 ) {
365+ if (a -> ss_family == WOLFSSL_IP6 ) {
353366 SOCKADDR_IN6 * a6 , * b6 ;
354367
355368 if (aLen < (XSOCKLENT )sizeof (SOCKADDR_IN6 ))
@@ -367,11 +380,20 @@ static int sockAddrEqual(
367380
368381 return 1 ;
369382 }
370- #endif /* WOLFSSL_HAVE_IPV6 */
383+ #endif /* WOLFSSL_IPV6 */
371384
372385 return 0 ;
373386}
374387
388+ #ifndef WOLFSSL_IPV6
389+ static int PeerIsIpv6 (const SOCKADDR_S * peer , XSOCKLENT len )
390+ {
391+ if (len < sizeof (peer -> ss_family ))
392+ return 0 ;
393+ return peer -> ss_family == WOLFSSL_IP6 ;
394+ }
395+ #endif /* !WOLFSSL_IPV6 */
396+
375397static int isDGramSock (int sfd )
376398{
377399 char type = 0 ;
@@ -400,13 +422,24 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
400422 SOCKADDR_S lclPeer ;
401423 SOCKADDR_S * peer ;
402424 XSOCKLENT peerSz = 0 ;
425+ #ifndef NO_ASN_TIME
426+ word32 start = 0 ;
427+ #elif !defined(DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER )
428+ word32 invalidPeerPackets = 0 ;
429+ #endif
403430
404431 WOLFSSL_ENTER ("EmbedReceiveFrom" );
405432
406433 if (dtlsCtx -> connected ) {
407434 peer = NULL ;
408435 }
409436 else if (dtlsCtx -> userSet ) {
437+ #ifndef WOLFSSL_IPV6
438+ if (PeerIsIpv6 ((SOCKADDR_S * )dtlsCtx -> peer .sa , dtlsCtx -> peer .sz )) {
439+ WOLFSSL_MSG ("ipv6 dtls peer set but no ipv6 support compiled" );
440+ return NOT_COMPILED_IN ;
441+ }
442+ #endif
410443 peer = & lclPeer ;
411444 XMEMSET (& lclPeer , 0 , sizeof (lclPeer ));
412445 peerSz = sizeof (lclPeer );
@@ -438,10 +471,26 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
438471 }
439472#endif /* WOLFSSL_DTLS13 */
440473
441- if (!doDtlsTimeout )
442- dtls_timeout = 0 ;
474+ do {
443475
444- if (!wolfSSL_get_using_nonblock (ssl )) {
476+ if (!doDtlsTimeout ) {
477+ dtls_timeout = 0 ;
478+ }
479+ else {
480+ #ifndef NO_ASN_TIME
481+ if (start == 0 ) {
482+ start = LowResTimer ();
483+ }
484+ else {
485+ dtls_timeout -= LowResTimer () - start ;
486+ start = LowResTimer ();
487+ if (dtls_timeout < 0 || dtls_timeout > DTLS_TIMEOUT_MAX )
488+ return WOLFSSL_CBIO_ERR_TIMEOUT ;
489+ }
490+ #endif
491+ }
492+
493+ if (!wolfSSL_get_using_nonblock (ssl )) {
445494 #ifdef USE_WINDOWS_API
446495 DWORD timeout = dtls_timeout * 1000 ;
447496 #ifdef WOLFSSL_DTLS13
@@ -464,87 +513,101 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
464513 #endif /* WOLFSSL_DTLS13 */
465514 timeout .tv_sec = dtls_timeout ;
466515 #endif
467- if (setsockopt (sd , SOL_SOCKET , SO_RCVTIMEO , (char * )& timeout ,
468- sizeof (timeout )) != 0 ) {
516+ if (setsockopt (sd , SOL_SOCKET , SO_RCVTIMEO , (char * )& timeout ,
517+ sizeof (timeout )) != 0 ) {
469518 WOLFSSL_MSG ("setsockopt rcvtimeo failed" );
519+ }
470520 }
471- }
472521#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 ();
522+ else if (IsSCR (ssl )) {
523+ if (ssl -> dtls_start_timeout &&
524+ LowResTimer () - ssl -> dtls_start_timeout >
525+ (word32 )dtls_timeout ) {
526+ ssl -> dtls_start_timeout = 0 ;
527+ return WOLFSSL_CBIO_ERR_TIMEOUT ;
528+ }
529+ else if (!ssl -> dtls_start_timeout ) {
530+ ssl -> dtls_start_timeout = LowResTimer ();
531+ }
481532 }
482- }
483533#endif /* !NO_ASN_TIME */
484534
485- recvd = (int )DTLS_RECVFROM_FUNCTION (sd , buf , sz , ssl -> rflags ,
486- (SOCKADDR * )peer , peer != NULL ? & peerSz : NULL );
535+ recvd = (int )DTLS_RECVFROM_FUNCTION (sd , buf , sz , ssl -> rflags ,
536+ (SOCKADDR * )peer , peer != NULL ? & peerSz : NULL );
487537
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- }
538+ /* From the RECV(2) man page
539+ * The returned address is truncated if the buffer provided is too
540+ * small; in this case, addrlen will return a value greater than was
541+ * supplied to the call.
542+ */
543+ if (dtlsCtx -> connected ) {
544+ /* No need to sanitize the value of peerSz */
545+ }
546+ else if (dtlsCtx -> userSet ) {
547+ /* Truncate peer size */
548+ if (peerSz > (XSOCKLENT )sizeof (lclPeer ))
549+ peerSz = (XSOCKLENT )sizeof (lclPeer );
550+ }
551+ else {
552+ /* Truncate peer size */
553+ if (peerSz > (XSOCKLENT )dtlsCtx -> peer .bufSz )
554+ peerSz = (XSOCKLENT )dtlsCtx -> peer .bufSz ;
555+ }
506556
507- recvd = TranslateReturnCode (recvd , sd );
557+ recvd = TranslateReturnCode (recvd , sd );
508558
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 ;
559+ if (recvd < 0 ) {
560+ WOLFSSL_MSG ("Embed Receive From error" );
561+ recvd = TranslateIoError (recvd );
562+ if (recvd == WOLFSSL_CBIO_ERR_WANT_READ &&
563+ !wolfSSL_dtls_get_using_nonblock (ssl )) {
564+ recvd = WOLFSSL_CBIO_ERR_TIMEOUT ;
565+ }
566+ return recvd ;
515567 }
516- return recvd ;
517- }
518- else if (recvd == 0 ) {
519- if (!isDGramSock (sd )) {
520- /* Closed TCP connection */
521- recvd = WOLFSSL_CBIO_ERR_CONN_CLOSE ;
568+ else if (recvd == 0 ) {
569+ if (!isDGramSock (sd )) {
570+ /* Closed TCP connection */
571+ recvd = WOLFSSL_CBIO_ERR_CONN_CLOSE ;
572+ }
573+ else {
574+ WOLFSSL_MSG ("Ignoring 0-length datagram" );
575+ continue ;
576+ }
577+ return recvd ;
522578 }
523- else {
524- WOLFSSL_MSG ("Ignoring 0-length datagram" );
579+ else if (dtlsCtx -> connected ) {
580+ /* Nothing to do */
581+ }
582+ else if (dtlsCtx -> userSet ) {
583+ /* Check we received the packet from the correct peer */
584+ if (dtlsCtx -> peer .sz > 0 &&
585+ (peerSz != (XSOCKLENT )dtlsCtx -> peer .sz ||
586+ !sockAddrEqual (peer , peerSz , (SOCKADDR_S * )dtlsCtx -> peer .sa ,
587+ dtlsCtx -> peer .sz ))) {
588+ WOLFSSL_MSG (" Ignored packet from invalid peer" );
589+ #if defined(NO_ASN_TIME ) && \
590+ !defined(DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER )
591+ if (doDtlsTimeout ) {
592+ invalidPeerPackets ++ ;
593+ if (invalidPeerPackets > DTLS_RECEIVEFROM_MAX_INVALID_PEER )
594+ return wolfSSL_dtls_get_using_nonblock (ssl )
595+ ? WOLFSSL_CBIO_ERR_WANT_READ
596+ : WOLFSSL_CBIO_ERR_TIMEOUT ;
597+ }
598+ #endif /* NO_ASN_TIME && !DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER */
599+ continue ;
600+ }
525601 }
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 ;
602+ else {
603+ /* Store size of saved address */
604+ dtlsCtx -> peer .sz = peerSz ;
539605 }
540- }
541- else {
542- /* Store size of saved address */
543- dtlsCtx -> peer .sz = peerSz ;
544- }
545606#ifndef NO_ASN_TIME
546- ssl -> dtls_start_timeout = 0 ;
607+ ssl -> dtls_start_timeout = 0 ;
547608#endif /* !NO_ASN_TIME */
609+ break ;
610+ } while (1 );
548611
549612 return recvd ;
550613}
@@ -569,6 +632,12 @@ int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
569632 else if (!dtlsCtx -> connected ) {
570633 peer = (const SOCKADDR_S * )dtlsCtx -> peer .sa ;
571634 peerSz = dtlsCtx -> peer .sz ;
635+ #ifndef WOLFSSL_IPV6
636+ if (PeerIsIpv6 (peer , peerSz )) {
637+ WOLFSSL_MSG ("ipv6 dtls peer setted but no ipv6 support compiled" );
638+ return NOT_COMPILED_IN ;
639+ }
640+ #endif
572641 }
573642
574643 sent = (int )DTLS_SENDTO_FUNCTION (sd , buf , sz , ssl -> wflags ,
0 commit comments