static int conn_state(BIO *b, BIO_CONNECT *c) { int ret= -1,i; unsigned long l; char *p,*q; int (*cb)(const BIO *,int,int)=NULL; if (c->info_callback != NULL) cb=c->info_callback; for (;;) { switch (c->state) { case BIO_CONN_S_BEFORE: p=c->param_hostname; if (p == NULL) { BIOerr(BIO_F_CONN_STATE,BIO_R_NO_HOSTNAME_SPECIFIED); goto exit_loop; } for ( ; *p != '\0'; p++) { if ((*p == ':') || (*p == '/')) break; } i= *p; if ((i == ':') || (i == '/')) { *(p++)='\0'; if (i == ':') { for (q=p; *q; q++) if (*q == '/') { *q='\0'; break; } if (c->param_port != NULL) OPENSSL_free(c->param_port); c->param_port=BUF_strdup(p); } } if (c->param_port == NULL) { BIOerr(BIO_F_CONN_STATE,BIO_R_NO_PORT_SPECIFIED); ERR_add_error_data(2,"host=",c->param_hostname); goto exit_loop; } c->state=BIO_CONN_S_GET_IP; break; case BIO_CONN_S_GET_IP: if (BIO_get_host_ip(c->param_hostname,&(c->ip[0])) <= 0) goto exit_loop; c->state=BIO_CONN_S_GET_PORT; break; case BIO_CONN_S_GET_PORT: if (c->param_port == NULL) { /* abort(); */ goto exit_loop; } else if (BIO_get_port(c->param_port,&c->port) <= 0) goto exit_loop; c->state=BIO_CONN_S_CREATE_SOCKET; break; case BIO_CONN_S_CREATE_SOCKET: /* now setup address */ TINYCLR_SSL_MEMSET((char *)&c->them,0,sizeof(c->them)); c->them.sin_family=AF_INET; c->them.sin_port=TINYCLR_SSL_HTONS((unsigned short)c->port); l=(unsigned long) ((unsigned long)c->ip[0]<<24L)| ((unsigned long)c->ip[1]<<16L)| ((unsigned long)c->ip[2]<< 8L)| ((unsigned long)c->ip[3]); c->them.sin_addr.S_un.S_addr=TINYCLR_SSL_HTONL(l); c->state=BIO_CONN_S_CREATE_SOCKET; ret=TINYCLR_SSL_SOCKET(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL); if (ret == INVALID_SOCKET) { SYSerr(SYS_F_SOCKET,get_last_socket_error()); ERR_add_error_data(4,"host=",c->param_hostname, ":",c->param_port); BIOerr(BIO_F_CONN_STATE,BIO_R_UNABLE_TO_CREATE_SOCKET); goto exit_loop; } b->num=ret; c->state=BIO_CONN_S_NBIO; break; case BIO_CONN_S_NBIO: if (c->nbio) { if (!BIO_socket_nbio(b->num,1)) { BIOerr(BIO_F_CONN_STATE,BIO_R_ERROR_SETTING_NBIO); ERR_add_error_data(4,"host=", c->param_hostname, ":",c->param_port); goto exit_loop; } } c->state=BIO_CONN_S_CONNECT; #if defined(SO_KEEPALIVE) && !defined(OPENSSL_SYS_MPE) i=1; i=TINYCLR_SSL_SETSOCKOPT(b->num,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i)); if (i < 0) { SYSerr(SYS_F_SOCKET,get_last_socket_error()); ERR_add_error_data(4,"host=",c->param_hostname, ":",c->param_port); BIOerr(BIO_F_CONN_STATE,BIO_R_KEEPALIVE); goto exit_loop; } #endif break; case BIO_CONN_S_CONNECT: BIO_clear_retry_flags(b); ret=TINYCLR_SSL_CONNECT(b->num, (struct TINYCLR_SSL_SOCKADDR *)&c->them, sizeof(c->them)); b->retry_reason=0; if (ret < 0) { if (BIO_sock_should_retry(ret)) { BIO_set_retry_special(b); c->state=BIO_CONN_S_BLOCKED_CONNECT; b->retry_reason=BIO_RR_CONNECT; } else { SYSerr(SYS_F_CONNECT,get_last_socket_error()); ERR_add_error_data(4,"host=", c->param_hostname, ":",c->param_port); BIOerr(BIO_F_CONN_STATE,BIO_R_CONNECT_ERROR); } goto exit_loop; } else c->state=BIO_CONN_S_OK; break; case BIO_CONN_S_BLOCKED_CONNECT: i=BIO_sock_error(b->num); if (i) { BIO_clear_retry_flags(b); SYSerr(SYS_F_CONNECT,i); ERR_add_error_data(4,"host=", c->param_hostname, ":",c->param_port); BIOerr(BIO_F_CONN_STATE,BIO_R_NBIO_CONNECT_ERROR); ret=0; goto exit_loop; } else c->state=BIO_CONN_S_OK; break; case BIO_CONN_S_OK: ret=1; goto exit_loop; default: /* TINYCLR_SSL_ABORT(); */ goto exit_loop; } if (cb != NULL) { if (!(ret=cb((BIO *)b,c->state,ret))) goto end; } } /* Loop does not exit */ exit_loop: if (cb != NULL) ret=cb((BIO *)b,c->state,ret); end: return(ret); }
void Test_OpenSSL_ClientServerAuth() { LCD_Clear(); lcd_printf("Testing SSL Client/Server negotiations...\n"); int err; int client_numbytes, server_numbytes; int listen_sd; int server_sd; int client_sd; struct TINYCLR_SSL_SOCKADDR_IN sa_serv; struct TINYCLR_SSL_SOCKADDR_IN sa_cli; size_t client_len; SSL_CTX* server_ctx = NULL; SSL* server_ssl = NULL; X509* server_cert = NULL; SSL_CTX* client_ctx = NULL; SSL* client_ssl = NULL; X509* client_cert = NULL; char* str = NULL; char client_buf [256]; char server_buf [256]; SSL_METHOD *server_meth = NULL; SSL_METHOD *client_meth = NULL; BIO *cert = NULL; X509 *x = NULL; EVP_PKEY *pkey = NULL; // SSL preliminaries. // create client ssl client_meth = (SSL_METHOD*)SSLv3_client_method(); client_ctx = SSL_CTX_new (client_meth); if (!client_ctx) goto cleanup; server_meth = (SSL_METHOD*)SSLv3_server_method(); server_ctx = SSL_CTX_new (server_meth); if (!server_ctx) goto cleanup; if ((cert=BIO_new(BIO_s_mem())) == NULL) { TINYCLR_SSL_PRINTF("Unable to create new BIO"); goto cleanup; } BIO_puts(cert,server_pem); x=PEM_read_bio_X509_AUX(cert, NULL, 0, NULL); pkey=PEM_read_bio_PrivateKey(cert,NULL, server_ctx->default_passwd_callback,server_ctx->default_passwd_callback_userdata); //if (SSL_CTX_use_certificate_file(server_ctx, CERTF, SSL_FILETYPE_PEM) <= 0) { if (SSL_CTX_use_certificate(server_ctx, x) <= 0) { TINYCLR_SSL_PRINTF("Use certifcate chain file failed"); goto cleanup; } if (SSL_CTX_use_PrivateKey(server_ctx, pkey) <= 0) { TINYCLR_SSL_PRINTF("Unable to use Private Key"); goto cleanup; } if (!SSL_CTX_check_private_key(server_ctx)) { TINYCLR_SSL_PRINTF("Private key does not match the certificate public key\n"); goto cleanup; } //if (SSL_CTX_set_cipher_list(server_ctx, ); // ----------------------------------------------- // Prepare TCP socket for receiving connections listen_sd = TINYCLR_SSL_SOCKET (AF_INET, SOCK_STREAM, IPPROTO_TCP); if (listen_sd < 0) goto cleanup; // set it to non-blocking int nonblock = 1; err = TINYCLR_SSL_IOCTL(listen_sd,SOCK_FIONBIO,&nonblock); if (err < 0) { int wsa = TINYCLR_SSL_GETLASTSOCKETERROR(); TINYCLR_SSL_PRINTF("Nonblocking call failed for server: %d.\n", wsa); goto cleanup; } TINYCLR_SSL_MEMSET(&sa_serv, '\0', sizeof(sa_serv)); sa_serv.sin_family = AF_INET; sa_serv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); sa_serv.sin_port = TINYCLR_SSL_HTONS (1111); /* Server Port number */ TINYCLR_SSL_PRINTF("Binding to %d...\n", TINYCLR_SSL_NTOHS(sa_serv.sin_port)); err = TINYCLR_SSL_BIND(listen_sd, (struct TINYCLR_SSL_SOCKADDR*) &sa_serv, sizeof (sa_serv)); if (err < 0) { int wsa = TINYCLR_SSL_GETLASTSOCKETERROR(); TINYCLR_SSL_PRINTF("Bind Socket error %d\n", wsa); goto cleanup; } TINYCLR_SSL_PRINTF("Listening...\n"); /* Receive a TCP connection. */ err = TINYCLR_SSL_LISTEN (listen_sd, 5); if (err < 0) { int wsa = TINYCLR_SSL_GETLASTSOCKETERROR(); TINYCLR_SSL_PRINTF("Listen Socket error %d\n", wsa); goto cleanup; } // create a client socket client_sd = TINYCLR_SSL_SOCKET (AF_INET, SOCK_STREAM, IPPROTO_TCP); if (client_sd < 0) goto cleanup; // set it to non-blocking err = TINYCLR_SSL_IOCTL(client_sd,SOCK_FIONBIO,&nonblock); if (err < 0) { int wsa = TINYCLR_SSL_GETLASTSOCKETERROR(); TINYCLR_SSL_PRINTF("Nonblocking call failed for client: %d.\n", wsa); goto cleanup; } // Set up a tcp connection for client: Bind, Connect err == TINYCLR_SSL_CONNECT( client_sd, (const struct TINYCLR_SSL_SOCKADDR*)&sa_serv, sizeof(sa_serv)); if (err < 0) { int wsa = TINYCLR_SSL_GETLASTSOCKETERROR(); TINYCLR_SSL_PRINTF("Client connect failed with: %d.\n", wsa); } client_len = sizeof(sa_cli); char nodename[128] = ""; char servname[128] = ""; SOCK_addrinfo hints; SOCK_addrinfo *res = NULL; TINYCLR_SSL_MEMSET(&hints, '\0', sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; SOCK_getaddrinfo(nodename,servname,&hints,&res); SOCK_addrinfo *ptr = NULL; for (ptr=res; ptr!=NULL; ptr=ptr->ai_next) { struct sockaddr_in *ip = (struct sockaddr_in*) ptr->ai_addr; TINYCLR_SSL_PRINTF("Accepting connections on...%s:%d\n", inet_ntoa(ip->sin_addr), 1111 ); } int counter=0; do { server_sd = TINYCLR_SSL_ACCEPT (listen_sd, (struct TINYCLR_SSL_SOCKADDR*) &sa_cli, (int*)&client_len); Events_WaitForEvents(0,2000); TINYCLR_SSL_PRINTF("Accept again %d:%d\n", TINYCLR_SSL_GETLASTSOCKETERROR(), counter++); } while (server_sd == -1); TINYCLR_SSL_CLOSESOCKET (listen_sd); TINYCLR_SSL_PRINTF ("Connection from %lx, port %x\n", sa_cli.sin_addr.S_un.S_addr, sa_cli.sin_port); // connections are completed between server & client // now lets do the SSL negotiations // create server ssl server_ssl = SSL_new(server_ctx); if (server_ssl == NULL) goto cleanup; SSL_set_fd (server_ssl, server_sd); //Create server bio and set as non-blocking BIO* server_bio = BIO_new(BIO_s_socket()); if (server_bio == NULL) goto cleanup; //CHK_NULL(bio); BIO_set_nbio(server_bio,1); BIO_set_fd(server_bio, server_sd, BIO_NOCLOSE); SSL_set_bio(server_ssl,server_bio,server_bio); // create client ssl & connect client_ssl = SSL_new(client_ctx); if (client_ssl == NULL) goto cleanup; SSL_set_fd(client_ssl, client_sd); //Create client bio and set as non-blocking BIO* client_bio = BIO_new(BIO_s_socket()); if (client_bio == NULL) goto cleanup; BIO_set_nbio(client_bio,1); BIO_set_fd(client_bio, client_sd, BIO_NOCLOSE); SSL_set_bio(client_ssl,client_bio,client_bio); // loop until server accepts ssl client connect int ssl_err =0; do { err = SSL_connect(client_ssl); if (err <= 0) { ssl_err = SSL_get_error(client_ssl,err); TINYCLR_SSL_PRINTF("SSL_Connect error: %d\n", ssl_err); } Events_WaitForEvents(0,1000); err = SSL_accept (server_ssl); if (err <= 0) { ssl_err = SSL_get_error(server_ssl, err); TINYCLR_SSL_PRINTF("SSL_Accept error: %d\n", ssl_err); } Events_WaitForEvents(0,1000); } while (err != 1); //Get the cipher - opt TINYCLR_SSL_PRINTF("SSL connection using %s\n", SSL_get_cipher (server_ssl)); //Get client's certificate (note: beware of dynamic allocation) - opt client_cert = SSL_get_peer_certificate (server_ssl); if (client_cert != NULL) { TINYCLR_SSL_PRINTF("Client certificate:\n"); str = X509_NAME_oneline (X509_get_subject_name (client_cert), 0, 0); if (str == NULL) goto cleanup; TINYCLR_SSL_PRINTF("subject: %s\n", str); OPENSSL_free (str); str = X509_NAME_oneline (X509_get_issuer_name (client_cert), 0, 0); if (str == NULL) goto cleanup; TINYCLR_SSL_PRINTF("issuer: %s\n", str); OPENSSL_free (str); //We could do all sorts of certificate verification stuff here before // deallocating the certificate. X509_free (client_cert); } else TINYCLR_SSL_PRINTF("Client does not have certificate.\n"); //Get server's certificate (note: beware of dynamic allocation) - opt server_cert = SSL_get_peer_certificate (client_ssl); if (server_cert != NULL) { TINYCLR_SSL_PRINTF("Server certificate:\n"); str = X509_NAME_oneline (X509_get_subject_name (server_cert), 0, 0); if (str == NULL) goto cleanup; TINYCLR_SSL_PRINTF("subject: %s\n", str); OPENSSL_free (str); str = X509_NAME_oneline (X509_get_issuer_name (server_cert), 0, 0); if (str == NULL) goto cleanup; TINYCLR_SSL_PRINTF("issuer: %s\n", str); OPENSSL_free (str); /* We could do all sorts of certificate verification stuff here before deallocating the certificate. */ X509_free (server_cert); } else TINYCLR_SSL_PRINTF("Server with no certificate?!?!?.\n"); do { // DATA EXCHANGE - Receive message and send reply. err = SSL_write(client_ssl,"Hello World!",TINYCLR_SSL_STRLEN("Hello World!")); if (err <= 0) ssl_err = SSL_get_error(client_ssl, err); Events_WaitForEvents(0,1000); server_numbytes= SSL_read (server_ssl, server_buf, sizeof(server_buf) - 1); if (server_numbytes <= 0) ssl_err = SSL_get_error(server_ssl, server_numbytes); else server_buf[server_numbytes] = '\0'; Events_WaitForEvents(0,1000); err = SSL_write (server_ssl, "I hear you.", TINYCLR_SSL_STRLEN("I hear you.")); if (err <= 0) ssl_err = SSL_get_error(server_ssl, err); Events_WaitForEvents(0,1000); client_numbytes= SSL_read(client_ssl, client_buf, sizeof(client_buf) -1); if (client_numbytes <= 0) ssl_err = SSL_get_error(client_ssl, client_numbytes); else client_buf[client_numbytes] = '\0'; Events_WaitForEvents(0,1000); } while (err <= 0); TINYCLR_SSL_PRINTF("Server got %d chars:'%s'\n", server_numbytes, server_buf); TINYCLR_SSL_PRINTF("Client go %d chars:'%s'\n", client_numbytes, client_buf); /* Clean up. */ cleanup: if (pkey) EVP_PKEY_free(pkey); if (cert) BIO_free(cert); if (x) X509_free(x); TINYCLR_SSL_CLOSESOCKET(server_sd); if (server_ssl) SSL_shutdown(server_ssl); if (server_ssl) SSL_free (server_ssl); server_ssl = NULL; if (server_ctx) SSL_CTX_free(server_ctx); server_ctx = NULL; TINYCLR_SSL_CLOSESOCKET(client_sd); if (client_ssl) SSL_shutdown(client_ssl); if (client_ssl) SSL_free (client_ssl); client_ssl = NULL; if (client_ctx) SSL_CTX_free(client_ctx); client_ctx = NULL; }
static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr) { long ret=1; int *ip; struct TINYCLR_SSL_SOCKADDR *to = NULL; bio_dgram_data *data = NULL; #if defined(IP_MTU_DISCOVER) || defined(IP_MTU) long sockopt_val = 0; unsigned int sockopt_len = 0; #endif #ifdef OPENSSL_SYS_LINUX socklen_t addr_len; union { struct TINYCLR_SSL_SOCKADDR sa; struct TINYCLR_SSL_SOCKADDR_IN s4; #if OPENSSL_USE_IPV6 struct sockaddr_in6 s6; #endif } addr; #endif data = (bio_dgram_data *)b->ptr; switch (cmd) { case BIO_CTRL_RESET: num=0; case BIO_C_FILE_SEEK: ret=0; break; case BIO_C_FILE_TELL: case BIO_CTRL_INFO: ret=0; break; case BIO_C_SET_FD: dgram_clear(b); b->num= *((int *)ptr); b->shutdown=(int)num; b->init=1; break; case BIO_C_GET_FD: if (b->init) { ip=(int *)ptr; if (ip != NULL) *ip=b->num; ret=b->num; } else ret= -1; break; case BIO_CTRL_GET_CLOSE: ret=b->shutdown; break; case BIO_CTRL_SET_CLOSE: b->shutdown=(int)num; break; case BIO_CTRL_PENDING: case BIO_CTRL_WPENDING: ret=0; break; case BIO_CTRL_DUP: case BIO_CTRL_FLUSH: ret=1; break; case BIO_CTRL_DGRAM_CONNECT: to = (struct TINYCLR_SSL_SOCKADDR *)ptr; #if 0 if (TINYCLR_SSL_CONNECT(b->num, to, sizeof(struct TINYCLR_SSL_SOCKADDR)) < 0) { TINYCLR_SSL_PERROR("connect"); ret = 0; } else { #endif switch (to->sa_family) { case AF_INET: TINYCLR_SSL_MEMCPY(&data->peer,to,sizeof(data->peer.sa_in)); break; #if OPENSSL_USE_IPV6 case AF_INET6: TINYCLR_SSL_MEMCPY(&data->peer,to,sizeof(data->peer.sa_in6)); break; #endif default: TINYCLR_SSL_MEMCPY(&data->peer,to,sizeof(data->peer.sa)); break; } #if 0 } #endif break; /* (Linux)kernel sets DF bit on outgoing IP packets */ case BIO_CTRL_DGRAM_MTU_DISCOVER: #ifdef OPENSSL_SYS_LINUX addr_len = (socklen_t)sizeof(addr); TINYCLR_SSL_MEMSET((void *)&addr, 0, sizeof(addr)); if (getsockname(b->num, &addr.sa, &addr_len) < 0) { ret = 0; break; } sockopt_len = sizeof(sockopt_val); switch (addr.sa.sa_family) { case AF_INET: sockopt_val = IP_PMTUDISC_DO; if ((ret = TINYCLR_SSL_SETSOCKOPT(b->num, IPPROTO_IP, IP_MTU_DISCOVER, &sockopt_val, sizeof(sockopt_val))) < 0) TINYCLR_SSL_PERROR("setsockopt"); break; #if OPENSSL_USE_IPV6 && defined(IPV6_MTU_DISCOVER) case AF_INET6: sockopt_val = IPV6_PMTUDISC_DO; if ((ret = TINYCLR_SSL_SETSOCKOPT(b->num, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &sockopt_val, sizeof(sockopt_val))) < 0) TINYCLR_SSL_PERROR("setsockopt"); break; #endif default: ret = -1; break; } ret = -1; #else break; #endif case BIO_CTRL_DGRAM_QUERY_MTU: #ifdef OPENSSL_SYS_LINUX addr_len = (socklen_t)sizeof(addr); TINYCLR_SSL_MEMSET((void *)&addr, 0, sizeof(addr)); if (getsockname(b->num, &addr.sa, &addr_len) < 0) { ret = 0; break; } sockopt_len = sizeof(sockopt_val); switch (addr.sa.sa_family) { case AF_INET: if ((ret = TINYCLR_SSL_GETSOCKOPT(b->num, IPPROTO_IP, IP_MTU, (void *)&sockopt_val, &sockopt_len)) < 0 || sockopt_val < 0) { ret = 0; } else { /* we assume that the transport protocol is UDP and no * IP options are used. */ data->mtu = sockopt_val - 8 - 20; ret = data->mtu; } break; #if OPENSSL_USE_IPV6 && defined(IPV6_MTU) case AF_INET6: if ((ret = TINYCLR_SSL_GETSOCKOPT(b->num, IPPROTO_IPV6, IPV6_MTU, (void *)&sockopt_val, &sockopt_len)) < 0 || sockopt_val < 0) { ret = 0; } else { /* we assume that the transport protocol is UDP and no * IPV6 options are used. */ data->mtu = sockopt_val - 8 - 40; ret = data->mtu; } break; #endif default: ret = 0; break; } #else ret = 0; #endif break; case BIO_CTRL_DGRAM_GET_MTU: return data->mtu; break; case BIO_CTRL_DGRAM_SET_MTU: data->mtu = num; ret = num; break; case BIO_CTRL_DGRAM_SET_CONNECTED: to = (struct TINYCLR_SSL_SOCKADDR *)ptr; if ( to != NULL) { data->connected = 1; switch (to->sa_family) { case AF_INET: TINYCLR_SSL_MEMCPY(&data->peer,to,sizeof(data->peer.sa_in)); break; #if OPENSSL_USE_IPV6 case AF_INET6: TINYCLR_SSL_MEMCPY(&data->peer,to,sizeof(data->peer.sa_in6)); break; #endif default: TINYCLR_SSL_MEMCPY(&data->peer,to,sizeof(data->peer.sa)); break; } } else { data->connected = 0; TINYCLR_SSL_MEMSET(&(data->peer), 0x00, sizeof(data->peer)); } break; case BIO_CTRL_DGRAM_GET_PEER: switch (data->peer.sa.sa_family) { case AF_INET: ret=sizeof(data->peer.sa_in); break; #if OPENSSL_USE_IPV6 case AF_INET6: ret=sizeof(data->peer.sa_in6); break; #endif default: ret=sizeof(data->peer.sa); break; } if (num==0 || num>ret) num=ret; TINYCLR_SSL_MEMCPY(ptr,&data->peer,(ret=num)); break; case BIO_CTRL_DGRAM_SET_PEER: to = (struct TINYCLR_SSL_SOCKADDR *) ptr; switch (to->sa_family) { case AF_INET: TINYCLR_SSL_MEMCPY(&data->peer,to,sizeof(data->peer.sa_in)); break; #if OPENSSL_USE_IPV6 case AF_INET6: TINYCLR_SSL_MEMCPY(&data->peer,to,sizeof(data->peer.sa_in6)); break; #endif default: TINYCLR_SSL_MEMCPY(&data->peer,to,sizeof(data->peer.sa)); break; } break; case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT: TINYCLR_SSL_MEMCPY(&(data->next_timeout), ptr, sizeof(struct TINYCLR_SSL_TIMEVAL)); break; #if defined(SO_RCVTIMEO) case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT: #ifdef OPENSSL_SYS_WINDOWS { struct TINYCLR_SSL_TIMEVAL *tv = (struct TINYCLR_SSL_TIMEVAL *)ptr; int timeout = tv->tv_sec * 1000 + tv->tv_usec/1000; if (TINYCLR_SSL_SETSOCKOPT(b->num, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(timeout)) < 0) { TINYCLR_SSL_PERROR("setsockopt"); ret = -1; } } #else if ( TINYCLR_SSL_SETSOCKOPT(b->num, SOL_SOCKET, SO_RCVTIMEO, ptr, sizeof(struct TINYCLR_SSL_TIMEVAL)) < 0) { TINYCLR_SSL_PERROR("setsockopt"); ret = -1; } #endif break; case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT: #ifdef OPENSSL_SYS_WINDOWS { int timeout, sz = sizeof(timeout); struct TINYCLR_SSL_TIMEVAL *tv = (struct TINYCLR_SSL_TIMEVAL *)ptr; if (TINYCLR_SSL_GETSOCKOPT(b->num, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, &sz) < 0) { TINYCLR_SSL_PERROR("getsockopt"); ret = -1; } else { tv->tv_sec = timeout / 1000; tv->tv_usec = (timeout % 1000) * 1000; ret = sizeof(*tv); } } #elif defined(OPENSSL_SYS_ARM) || defined(OPENSSL_SYS_SH) if ( TINYCLR_SSL_GETSOCKOPT(b->num, SOL_SOCKET, SO_RCVTIMEO, ptr, (u32_t *)&ret) < 0) { TINYCLR_SSL_PERROR("getsockopt"); ret = -1; } #else if ( TINYCLR_SSL_GETSOCKOPT(b->num, SOL_SOCKET, SO_RCVTIMEO, ptr, (void *)&ret) < 0) { TINYCLR_SSL_PERROR("getsockopt"); ret = -1; } #endif break; #endif #if defined(SO_SNDTIMEO) case BIO_CTRL_DGRAM_SET_SEND_TIMEOUT: #ifdef OPENSSL_SYS_WINDOWS { struct TINYCLR_SSL_TIMEVAL *tv = (struct TINYCLR_SSL_TIMEVAL *)ptr; int timeout = tv->tv_sec * 1000 + tv->tv_usec/1000; if (TINYCLR_SSL_SETSOCKOPT(b->num, SOL_SOCKET, SO_SNDTIMEO, (const char*)&timeout, sizeof(timeout)) < 0) { TINYCLR_SSL_PERROR("setsockopt"); ret = -1; } } #else if ( TINYCLR_SSL_SETSOCKOPT(b->num, SOL_SOCKET, SO_SNDTIMEO, ptr, sizeof(struct TINYCLR_SSL_TIMEVAL)) < 0) { TINYCLR_SSL_PERROR("setsockopt"); ret = -1; } #endif break; case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT: #ifdef OPENSSL_SYS_WINDOWS { int timeout, sz = sizeof(timeout); struct TINYCLR_SSL_TIMEVAL *tv = (struct TINYCLR_SSL_TIMEVAL *)ptr; if (TINYCLR_SSL_GETSOCKOPT(b->num, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, &sz) < 0) { TINYCLR_SSL_PERROR("getsockopt"); ret = -1; } else { tv->tv_sec = timeout / 1000; tv->tv_usec = (timeout % 1000) * 1000; ret = sizeof(*tv); } } #elif defined(OPENSSL_SYS_ARM) || defined(OPENSSL_SYS_SH) if ( TINYCLR_SSL_GETSOCKOPT(b->num, SOL_SOCKET, SO_SNDTIMEO, ptr, (u32_t *)&ret) < 0) { TINYCLR_SSL_PERROR("getsockopt"); ret = -1; } #else if ( TINYCLR_SSL_GETSOCKOPT(b->num, SOL_SOCKET, SO_SNDTIMEO, ptr, (void *)&ret) < 0) { TINYCLR_SSL_PERROR("getsockopt"); ret = -1; } #endif break; #endif case BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP: /* fall-through */ case BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP: #ifdef OPENSSL_SYS_WINDOWS if ( data->_errno == WSAETIMEDOUT) #else if ( data->_errno == EAGAIN) #endif { ret = 1; data->_errno = 0; } else ret = 0; break; #ifdef EMSGSIZE case BIO_CTRL_DGRAM_MTU_EXCEEDED: if ( data->_errno == EMSGSIZE) { ret = 1; data->_errno = 0; } else ret = 0; break; #endif default: ret=0; break; } return(ret); }