DTLS Nonblocking Updates

Add command line option to the example server to fake a write block on a
specified DTLS sequence number in epoch 0.
This commit is contained in:
John Safranek
2018-12-18 11:40:04 -08:00
parent aa4de6e170
commit cc3c2ef683

View File

@ -115,6 +115,138 @@ static void err_sys_ex(int out, const char* msg)
}
}
#ifdef WOLFSSL_DTLS
/* Translates return codes returned from
* send() and recv() if need be.
*/
static WC_INLINE int TranslateReturnCode(int old, int sd)
{
(void)sd;
#if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
if (old == 0) {
errno = SOCKET_EWOULDBLOCK;
return -1; /* convert to BSD style wouldblock as error */
}
if (old < 0) {
errno = RTCS_geterror(sd);
if (errno == RTCSERR_TCP_CONN_CLOSING)
return 0; /* convert to BSD style closing */
if (errno == RTCSERR_TCP_CONN_RLSD)
errno = SOCKET_ECONNRESET;
if (errno == RTCSERR_TCP_TIMED_OUT)
errno = SOCKET_EAGAIN;
}
#endif
return old;
}
static WC_INLINE int wolfSSL_LastError(void)
{
#ifdef USE_WINDOWS_API
return WSAGetLastError();
#elif defined(EBSNET)
return xn_getlasterror();
#else
return errno;
#endif
}
/* wolfSSL Sock Addr */
struct WOLFSSL_TEST_SOCKADDR {
unsigned int sz; /* sockaddr size */
SOCKADDR_IN_T sa; /* pointer to the sockaddr_in or sockaddr_in6 */
};
typedef struct WOLFSSL_TEST_DTLS_CTX {
struct WOLFSSL_TEST_SOCKADDR peer;
int rfd;
int wfd;
int failOnce;
word32 blockSeq;
} WOLFSSL_TEST_DTLS_CTX;
static WC_INLINE int PeekSeq(const char* buf, word32* seq)
{
const char* c = buf + 3;
if ((c[0] | c[1] | c[2] | c[3]) == 0) {
*seq = (c[4] << 24) | (c[5] << 16) | (c[6] << 8) | c[7];
return 1;
}
return 0;
}
/* The send embedded callback
* return : nb bytes sent, or error
*/
static int TestEmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
{
WOLFSSL_TEST_DTLS_CTX* dtlsCtx = (WOLFSSL_TEST_DTLS_CTX*)ctx;
int sd = dtlsCtx->wfd;
int sent;
int len = sz;
int err;
(void)ssl;
WOLFSSL_ENTER("TestEmbedSendTo()");
if (dtlsCtx->failOnce) {
word32 seq = 0;
if (PeekSeq(buf, &seq) && seq == dtlsCtx->blockSeq) {
dtlsCtx->failOnce = 0;
WOLFSSL_MSG("Forcing WANT_WRITE");
return WOLFSSL_CBIO_ERR_WANT_WRITE;
}
}
sent = (int)sendto(sd, &buf[sz - len], len, 0,
(const SOCKADDR*)&dtlsCtx->peer.sa,
dtlsCtx->peer.sz);
sent = TranslateReturnCode(sent, sd);
if (sent < 0) {
err = wolfSSL_LastError();
WOLFSSL_MSG("Embed Send To error");
if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
WOLFSSL_MSG("\tWould Block");
return WOLFSSL_CBIO_ERR_WANT_WRITE;
}
else if (err == SOCKET_ECONNRESET) {
WOLFSSL_MSG("\tConnection reset");
return WOLFSSL_CBIO_ERR_CONN_RST;
}
else if (err == SOCKET_EINTR) {
WOLFSSL_MSG("\tSocket interrupted");
return WOLFSSL_CBIO_ERR_ISR;
}
else if (err == SOCKET_EPIPE) {
WOLFSSL_MSG("\tSocket EPIPE");
return WOLFSSL_CBIO_ERR_CONN_CLOSE;
}
else {
WOLFSSL_MSG("\tGeneral error");
return WOLFSSL_CBIO_ERR_GENERAL;
}
}
return sent;
}
#endif /* WOLFSSL_DTLS */
static int NonBlockingSSL_Accept(SSL* ssl)
{
#ifndef WOLFSSL_CALLBACKS
@ -687,6 +819,9 @@ static void Usage(void)
!defined(HAVE_SELFTEST) && !defined(WOLFSSL_OLD_PRIME_CHECK)
printf("-2 Disable DH Prime check\n");
#endif
#ifdef WOLFSSL_DTLS
printf("-4 <seq> DTLS fake would-block for message seq\n");
#endif
#ifdef WOLFSSL_MULTICAST
printf("%s", msg[++msgId]); /* -3 */
#endif
@ -728,6 +863,10 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
int dtlsUDP = 0;
int dtlsSCTP = 0;
int doMcast = 0;
#ifdef WOLFSSL_DTLS
int doBlockSeq = 0;
WOLFSSL_TEST_DTLS_CTX dtlsCtx;
#endif
int needDH = 0;
int useNtruKey = 0;
int nonBlocking = 0;
@ -872,7 +1011,7 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
while ((ch = mygetopt(argc, argv, "?"
"abc:defgijk:l:mnop:q:rstuv:wxy"
"A:B:C:D:E:GH:IJKL:MNO:PQR:S:TUVYZ:"
"01:23:")) != -1) {
"01:23:4:")) != -1) {
switch (ch) {
case '?' :
if(myoptarg!=NULL) {
@ -1228,6 +1367,14 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
#endif
break;
case '4' :
#ifdef WOLFSSL_DTLS
XMEMSET(&dtlsCtx, 0, sizeof(dtlsCtx));
doBlockSeq = 1;
dtlsCtx.blockSeq = atoi(myoptarg);
#endif
break;
default:
Usage();
XEXIT_T(MY_EX_USAGE);
@ -1607,6 +1754,14 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
#endif
}
if (doDTLS && dtlsUDP) {
#ifdef WOLFSSL_DTLS
if (doBlockSeq) {
wolfSSL_CTX_SetIOSend(ctx, TestEmbedSendTo);
}
#endif
}
#ifdef HAVE_PK_CALLBACKS
if (pkCallbacks)
SetupPkCallbacks(ctx);
@ -1816,12 +1971,22 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
/* For DTLS, peek at the next datagram so we can get the client's
* address and set it into the ssl object later to generate the
* cookie. */
n = (int)recvfrom(sockfd, (char*)b, sizeof(b), MSG_PEEK,
n = (int)recvfrom(clientfd, (char*)b, sizeof(b), MSG_PEEK,
(struct sockaddr*)&cliaddr, &len);
if (n <= 0)
err_sys_ex(runWithErrors, "recvfrom failed");
wolfSSL_dtls_set_peer(ssl, &cliaddr, len);
if (doBlockSeq) {
XMEMCPY(&dtlsCtx.peer.sa, &cliaddr, len);
dtlsCtx.peer.sz = len;
dtlsCtx.wfd = clientfd;
dtlsCtx.failOnce = 1;
wolfSSL_SetIOWriteCtx(ssl, &dtlsCtx);
}
else {
wolfSSL_dtls_set_peer(ssl, &cliaddr, len);
}
}
#endif
if ((usePsk == 0 || usePskPlus) || useAnon == 1 || cipherList != NULL