From 46e92e0211f2b4ff201c08170d9025b2970f6a7d Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 25 Aug 2016 22:20:35 -0700 Subject: [PATCH] DTLS-SCTP example client and server 1. Update the example client and server to test DTLS-SCTP. 2. Modify the test.h functions for setting up connections to allow for a SCTP option. 3. Update other examples to use the new test.h functions. 4. Removed some prototypes in the client header file were some functions that should have been static to the client.c file and made them static. --- examples/client/client.c | 53 ++++++++++++++++++++++---------- examples/client/client.h | 15 --------- examples/echoclient/echoclient.c | 2 +- examples/echoserver/echoserver.c | 4 +-- examples/server/server.c | 36 ++++++++++++++++++---- tests/api.c | 15 +++++---- wolfssl/test.h | 44 ++++++++++++++++---------- 7 files changed, 107 insertions(+), 62 deletions(-) diff --git a/examples/client/client.c b/examples/client/client.c index f814c0d4e..67ae69cd8 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -156,8 +156,10 @@ static void ShowVersions(void) printf("3\n"); } -int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, - int doDTLS, int benchmark, int resumeSession) +/* Measures average time to create, connect and disconnect a connection (TPS). +Benchmark = number of connections. */ +static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, + int dtlsUDP, int dtlsSCTP, int benchmark, int resumeSession) { /* time passed in number of connects give average */ int times = benchmark; @@ -180,7 +182,7 @@ int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, if (ssl == NULL) err_sys("unable to get SSL object"); - tcp_connect(&sockfd, host, port, doDTLS, ssl); + tcp_connect(&sockfd, host, port, dtlsUDP, dtlsSCTP, ssl); #ifndef NO_SESSION_CACHE if (benchResume) @@ -215,8 +217,9 @@ int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, return EXIT_SUCCESS; } -int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, - int doDTLS, int throughput) +/* Measures throughput in kbps. Throughput = number of bytes */ +static int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, + int dtlsUDP, int dtlsSCTP, int throughput) { double start, conn_time = 0, tx_time = 0, rx_time = 0; SOCKET_T sockfd; @@ -227,7 +230,7 @@ int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, ssl = wolfSSL_new(ctx); if (ssl == NULL) err_sys("unable to get SSL object"); - tcp_connect(&sockfd, host, port, doDTLS, ssl); + tcp_connect(&sockfd, host, port, dtlsUDP, dtlsSCTP, ssl); if (wolfSSL_set_fd(ssl, sockfd) != SSL_SUCCESS) { err_sys("error in setting fd"); } @@ -343,7 +346,8 @@ const char* starttlsCmd[6] = { "QUIT\r\n", }; -int StartTLS_Init(SOCKET_T* sockfd) +/* Initiates the STARTTLS command sequence over TCP */ +static int StartTLS_Init(SOCKET_T* sockfd) { char tmpBuf[256]; @@ -399,7 +403,8 @@ int StartTLS_Init(SOCKET_T* sockfd) return SSL_SUCCESS; } -int SMTP_Shutdown(WOLFSSL* ssl, int wc_shutdown) +/* Closes down the SMTP connection */ +static int SMTP_Shutdown(WOLFSSL* ssl, int wc_shutdown) { int ret; char tmpBuf[256]; @@ -461,6 +466,10 @@ static void Usage(void) printf("-g Send server HTTP GET\n"); printf("-u Use UDP DTLS," " add -v 2 for DTLSv1, -v 3 for DTLSv1.2 (default)\n"); +#ifdef WOLFSSL_SCTP + printf("-G Use SCTP DTLS," + " add -v 2 for DTLSv1, -v 3 for DTLSv1.2 (default)\n"); +#endif printf("-m Match domain name in cert\n"); printf("-N Use Non-blocking sockets\n"); printf("-r Resume session\n"); @@ -551,6 +560,8 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) int benchmark = 0; int throughput = 0; int doDTLS = 0; + int dtlsUDP = 0; + int dtlsSCTP = 0; int matchName = 0; int doPeerCheck = 1; int nonBlocking = 0; @@ -640,7 +651,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifndef WOLFSSL_VXWORKS while ((ch = mygetopt(argc, argv, - "?gdeDusmNrwRitfxXUPCVh:p:v:l:A:c:k:Z:b:zS:F:L:ToO:aB:W:E:M:q:")) + "?gdeDuGsmNrwRitfxXUPCVh:p:v:l:A:c:k:Z:b:zS:F:L:ToO:aB:W:E:M:q:")) != -1) { switch (ch) { case '?' : @@ -670,7 +681,15 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) break; case 'u' : - doDTLS = 1; + doDTLS = 1; + dtlsUDP = 1; + break; + + case 'G' : + #ifdef WOLFSSL_SCTP + doDTLS = 1; + dtlsSCTP = 1; + #endif break; case 's' : @@ -1212,14 +1231,16 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if (benchmark) { ((func_args*)args)->return_code = - ClientBenchmarkConnections(ctx, host, port, doDTLS, benchmark, resumeSession); + ClientBenchmarkConnections(ctx, host, port, dtlsUDP, dtlsSCTP, + benchmark, resumeSession); wolfSSL_CTX_free(ctx); exit(EXIT_SUCCESS); } if(throughput) { ((func_args*)args)->return_code = - ClientBenchmarkThroughput(ctx, host, port, doDTLS, throughput); + ClientBenchmarkThroughput(ctx, host, port, dtlsUDP, dtlsSCTP, + throughput); wolfSSL_CTX_free(ctx); exit(EXIT_SUCCESS); } @@ -1305,7 +1326,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) } #endif - tcp_connect(&sockfd, host, port, doDTLS, ssl); + tcp_connect(&sockfd, host, port, dtlsUDP, dtlsSCTP, ssl); if (wolfSSL_set_fd(ssl, sockfd) != SSL_SUCCESS) { err_sys("error in setting fd"); } @@ -1484,7 +1505,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) } #endif - if (doDTLS == 0) { /* don't send alert after "break" command */ + if (dtlsUDP == 0) { /* don't send alert after "break" command */ ret = wolfSSL_shutdown(ssl); if (wc_shutdown && ret == SSL_SHUTDOWN_NOT_DONE) wolfSSL_shutdown(ssl); /* bidirectional shutdown */ @@ -1498,7 +1519,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifndef NO_SESSION_CACHE if (resumeSession) { - if (doDTLS) { + if (dtlsUDP) { #ifdef USE_WINDOWS_API Sleep(500); #elif defined(WOLFSSL_TIRTOS) @@ -1507,7 +1528,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) sleep(1); #endif } - tcp_connect(&sockfd, host, port, doDTLS, sslResume); + tcp_connect(&sockfd, host, port, dtlsUDP, dtlsSCTP, sslResume); if (wolfSSL_set_fd(sslResume, sockfd) != SSL_SUCCESS) { err_sys("error in setting fd"); } diff --git a/examples/client/client.h b/examples/client/client.h index 913339ac0..39456a4f5 100644 --- a/examples/client/client.h +++ b/examples/client/client.h @@ -26,21 +26,6 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args); -/* Measures average time to create, connect and disconnect a connection (TPS). -Benchmark = number of connections. */ -int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, - int doDTLS, int benchmark, int resumeSession); - -/* Measures throughput in kbps. Throughput = number of bytes */ -int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, - int doDTLS, int throughput); - -/* Initiates the STARTTLS command sequence over TCP */ -int StartTLS_Init(SOCKET_T* sockfd); - -/* Closes down the SMTP connection */ -int SMTP_Shutdown(WOLFSSL* ssl, int wc_shutdown); - #endif /* WOLFSSL_CLIENT_H */ diff --git a/examples/echoclient/echoclient.c b/examples/echoclient/echoclient.c index 6cb836e6a..1c06efa83 100644 --- a/examples/echoclient/echoclient.c +++ b/examples/echoclient/echoclient.c @@ -180,7 +180,7 @@ void echoclient_test(void* args) #endif /* WOLFSSL_ASYNC_CRYPT */ ssl = SSL_new(ctx); - tcp_connect(&sockfd, yasslIP, port, doDTLS, ssl); + tcp_connect(&sockfd, yasslIP, port, doDTLS, 0, ssl); SSL_set_fd(ssl, sockfd); #if defined(USE_WINDOWS_API) && defined(CYASSL_DTLS) && defined(NO_MAIN_DRIVER) diff --git a/examples/echoserver/echoserver.c b/examples/echoserver/echoserver.c index d917c946b..432525806 100644 --- a/examples/echoserver/echoserver.c +++ b/examples/echoserver/echoserver.c @@ -136,7 +136,7 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) fdOpenSession(Task_self()); #endif - tcp_listen(&sockfd, &port, useAnyAddr, doDTLS); + tcp_listen(&sockfd, &port, useAnyAddr, doDTLS, 0); #if defined(CYASSL_DTLS) method = CyaDTLSv1_2_server_method(); @@ -373,7 +373,7 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) CyaSSL_free(ssl); CloseSocket(clientfd); #ifdef CYASSL_DTLS - tcp_listen(&sockfd, &port, useAnyAddr, doDTLS); + tcp_listen(&sockfd, &port, useAnyAddr, doDTLS, 0); SignalReady(args, port); #endif } diff --git a/examples/server/server.c b/examples/server/server.c index 74feccc0b..3dd98554e 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -219,6 +219,10 @@ static void Usage(void) printf("-t Track wolfSSL memory use\n"); printf("-u Use UDP DTLS," " add -v 2 for DTLSv1, -v 3 for DTLSv1.2 (default)\n"); +#ifdef WOLFSSL_SCTP + printf("-G Use SCTP DTLS," + " add -v 2 for DTLSv1, -v 3 for DTLSv1.2 (default)\n"); +#endif printf("-f Fewer packets/group messages\n"); printf("-r Allow one client Resumption\n"); printf("-N Use Non-blocking sockets\n"); @@ -275,6 +279,8 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) int usePskPlus = 0; int useAnon = 0; int doDTLS = 0; + int dtlsUDP = 0; + int dtlsSCTP = 0; int needDH = 0; int useNtruKey = 0; int nonBlocking = 0; @@ -370,7 +376,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) useAnyAddr = 1; #else while ((ch = mygetopt(argc, argv, - "?jdbstnNufrawPIR:p:v:l:A:c:k:Z:S:oO:D:L:ieB:E:q:")) != -1) { + "?jdbstnNuGfrawPIR:p:v:l:A:c:k:Z:S:oO:D:L:ieB:E:q:")) != -1) { switch (ch) { case '?' : Usage(); @@ -404,6 +410,14 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) case 'u' : doDTLS = 1; + dtlsUDP = 1; + break; + + case 'G' : + #ifdef WOLFSSL_SCTP + doDTLS = 1; + dtlsSCTP = 1; + #endif break; case 'f' : @@ -563,6 +577,11 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) myoptind = 0; /* reset for test cases */ #endif /* !WOLFSSL_VXWORKS */ + /* Can only use DTLS over UDP or SCTP, can't do both. */ + if (dtlsUDP && dtlsSCTP) { + err_sys("Cannot use DTLS with both UDP and SCTP."); + } + /* sort out DTLS versus TLS versions */ if (version == CLIENT_INVALID_VERSION) { if (doDTLS) @@ -689,6 +708,11 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) if (fewerPackets) CyaSSL_CTX_set_group_messages(ctx); +#ifdef WOLFSSL_SCTP + if (dtlsSCTP) + wolfSSL_CTX_dtls_set_sctp(ctx); +#endif + #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) SSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif @@ -821,13 +845,13 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) while (1) { /* allow resume option */ if(resumeCount > 1) { - if (doDTLS == 0) { + if (dtlsUDP == 0) { SOCKADDR_IN_T client; socklen_t client_len = sizeof(client); clientfd = accept(sockfd, (struct sockaddr*)&client, (ACCEPT_THIRD_T)&client_len); } else { - tcp_listen(&sockfd, &port, useAnyAddr, doDTLS); + tcp_listen(&sockfd, &port, useAnyAddr, dtlsUDP, dtlsSCTP); clientfd = sockfd; } if(WOLFSSL_SOCKET_IS_INVALID(clientfd)) { @@ -908,7 +932,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) readySignal->srfName = serverReadyFile; } tcp_accept(&sockfd, &clientfd, (func_args*)args, port, useAnyAddr, - doDTLS, serverReadyFile ? 1 : 0, doListen); + dtlsUDP, dtlsSCTP, serverReadyFile ? 1 : 0, doListen); doListen = 0; /* Don't listen next time */ if (SSL_set_fd(ssl, clientfd) != SSL_SUCCESS) { @@ -923,7 +947,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #endif #ifdef WOLFSSL_DTLS - if (doDTLS) { + if (doDTLS && dtlsUDP) { SOCKADDR_IN_T cliaddr; byte b[1500]; int n; @@ -1039,7 +1063,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) Task_yield(); #endif - if (doDTLS == 0) { + if (dtlsUDP == 0) { ret = SSL_shutdown(ssl); if (wc_shutdown && ret == SSL_SHUTDOWN_NOT_DONE) SSL_shutdown(ssl); /* bidirectional shutdown */ diff --git a/tests/api.c b/tests/api.c index a24941698..11605d1ce 100644 --- a/tests/api.c +++ b/tests/api.c @@ -672,7 +672,7 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args) } ssl = wolfSSL_new(ctx); - tcp_accept(&sockfd, &clientfd, (func_args*)args, port, 0, 0, 0, 1); + tcp_accept(&sockfd, &clientfd, (func_args*)args, port, 0, 0, 0, 0, 1); CloseSocket(sockfd); if (wolfSSL_set_fd(ssl, clientfd) != SSL_SUCCESS) { @@ -800,7 +800,8 @@ static void test_client_nofail(void* args) } ssl = wolfSSL_new(ctx); - tcp_connect(&sockfd, wolfSSLIP, ((func_args*)args)->signal->port, 0, ssl); + tcp_connect(&sockfd, wolfSSLIP, ((func_args*)args)->signal->port, + 0, 0, ssl); if (wolfSSL_set_fd(ssl, sockfd) != SSL_SUCCESS) { /*err_sys("SSL_set_fd failed");*/ goto done2; @@ -919,14 +920,14 @@ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args) socklen_t cliLen; cliLen = sizeof(cliAddr); - tcp_accept(&sfd, &cfd, (func_args*)args, port, 0, 1, 0, 0); + tcp_accept(&sfd, &cfd, (func_args*)args, port, 0, 1, 0, 0, 0); idx = (int)recvfrom(sfd, input, sizeof(input), MSG_PEEK, (struct sockaddr*)&cliAddr, &cliLen); AssertIntGT(idx, 0); wolfSSL_dtls_set_peer(ssl, &cliAddr, cliLen); } else { - tcp_accept(&sfd, &cfd, (func_args*)args, port, 0, 0, 0, 1); + tcp_accept(&sfd, &cfd, (func_args*)args, port, 0, 0, 0, 0, 1); CloseSocket(sfd); } @@ -1051,10 +1052,12 @@ static void run_wolfssl_client(void* args) ssl = wolfSSL_new(ctx); if (wolfSSL_dtls(ssl)) { - tcp_connect(&sfd, wolfSSLIP, ((func_args*)args)->signal->port, 1, ssl); + tcp_connect(&sfd, wolfSSLIP, ((func_args*)args)->signal->port, + 1, 0, ssl); } else { - tcp_connect(&sfd, wolfSSLIP, ((func_args*)args)->signal->port, 0, ssl); + tcp_connect(&sfd, wolfSSLIP, ((func_args*)args)->signal->port, + 0, 0, ssl); } AssertIntEQ(SSL_SUCCESS, wolfSSL_set_fd(ssl, sfd)); diff --git a/wolfssl/test.h b/wolfssl/test.h index f23748ee4..c0197d590 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -564,11 +564,12 @@ static INLINE void showPeer(WOLFSSL* ssl) static INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer, - word16 port, int udp) + word16 port, int udp, int sctp) { int useLookup = 0; (void)useLookup; (void)udp; + (void)sctp; if (addr == NULL) err_sys("invalid argument to build_addr, addr is NULL"); @@ -628,8 +629,17 @@ static INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer, memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET_V; - hints.ai_socktype = udp ? SOCK_DGRAM : SOCK_STREAM; - hints.ai_protocol = udp ? IPPROTO_UDP : IPPROTO_TCP; + if (udp) { + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + } else if (sctp) { + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_SCTP; + } + else { + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + } SNPRINTF(strPort, sizeof(strPort), "%d", port); strPort[79] = '\0'; @@ -649,10 +659,12 @@ static INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer, } -static INLINE void tcp_socket(SOCKET_T* sockfd, int udp) +static INLINE void tcp_socket(SOCKET_T* sockfd, int udp, int sctp) { if (udp) *sockfd = socket(AF_INET_V, SOCK_DGRAM, 0); + else if (sctp) + *sockfd = socket(AF_INET_V, SOCK_STREAM, 0); else *sockfd = socket(AF_INET_V, SOCK_STREAM, 0); @@ -677,7 +689,7 @@ static INLINE void tcp_socket(SOCKET_T* sockfd, int udp) #endif /* S_NOSIGPIPE */ #if defined(TCP_NODELAY) - if (!udp) + if (!udp && !sctp) { int on = 1; socklen_t len = sizeof(on); @@ -690,14 +702,14 @@ static INLINE void tcp_socket(SOCKET_T* sockfd, int udp) } static INLINE void tcp_connect(SOCKET_T* sockfd, const char* ip, word16 port, - int udp, WOLFSSL* ssl) + int udp, int sctp, WOLFSSL* ssl) { SOCKADDR_IN_T addr; - build_addr(&addr, ip, port, udp); - if(udp) { + build_addr(&addr, ip, port, udp, sctp); + if (udp) { wolfSSL_dtls_set_peer(ssl, &addr, sizeof(addr)); } - tcp_socket(sockfd, udp); + tcp_socket(sockfd, udp, sctp); if (!udp) { if (connect(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0) @@ -757,14 +769,14 @@ static INLINE int tcp_select(SOCKET_T socketfd, int to_sec) static INLINE void tcp_listen(SOCKET_T* sockfd, word16* port, int useAnyAddr, - int udp) + int udp, int sctp) { SOCKADDR_IN_T addr; /* don't use INADDR_ANY by default, firewall may block, make user switch on */ - build_addr(&addr, (useAnyAddr ? INADDR_ANY : wolfSSLIP), *port, udp); - tcp_socket(sockfd, udp); + build_addr(&addr, (useAnyAddr ? INADDR_ANY : wolfSSLIP), *port, udp, sctp); + tcp_socket(sockfd, udp, sctp); #if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_MDK_ARM)\ && !defined(WOLFSSL_KEIL_TCP_NET) @@ -826,8 +838,8 @@ static INLINE void udp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd, SOCKADDR_IN_T addr; (void)args; - build_addr(&addr, (useAnyAddr ? INADDR_ANY : wolfSSLIP), port, 1); - tcp_socket(sockfd, 1); + build_addr(&addr, (useAnyAddr ? INADDR_ANY : wolfSSLIP), port, 1, 0); + tcp_socket(sockfd, 1, 0); #if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_MDK_ARM) \ @@ -879,7 +891,7 @@ static INLINE void udp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd, static INLINE void tcp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd, func_args* args, word16 port, int useAnyAddr, - int udp, int ready_file, int do_listen) + int udp, int sctp, int ready_file, int do_listen) { SOCKADDR_IN_T client; socklen_t client_len = sizeof(client); @@ -893,7 +905,7 @@ static INLINE void tcp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd, } if(do_listen) { - tcp_listen(sockfd, &port, useAnyAddr, udp); + tcp_listen(sockfd, &port, useAnyAddr, udp, sctp); #if defined(_POSIX_THREADS) && defined(NO_MAIN_DRIVER) && !defined(__MINGW32__) /* signal ready to tcp_accept */