/** * Read a from a stream and handle restarts if nessecary */ ssize_t read_from_stream(BIO* bio, char* buffer, ssize_t length) { ssize_t r = -1; while (r < 0) { r = BIO_read(bio, buffer, length); if (r == 0) { print_ssl_error("Reached the end of the data stream.\n", stdout); continue; } else if (r < 0) { if (!BIO_should_retry(bio)) { print_ssl_error("BIO_read should retry test failed.\n", stdout); continue; } /* It would be prudent to check the reason for the retry and handle * it appropriately here */ } }; return r; }
/* Load private key and certificate from file */ int ssl_load_key_cert(char *file, rsa_context **private_key, x509_cert **certificate) { int result; if (file == NULL) { return -1; } if ((*private_key = (rsa_context*)malloc(sizeof(rsa_context))) == NULL) { return -1; } memset(*private_key, 0, sizeof(rsa_context)); if ((result = x509parse_keyfile(*private_key, file, NULL)) != 0) { print_ssl_error("Error loading RSA private key", result); return -1; } if ((*certificate = (x509_cert*)malloc(sizeof(x509_cert))) == NULL) { return -1; } memset(*certificate, 0, sizeof(x509_cert)); if ((result = x509parse_crtfile(*certificate, file)) != 0) { print_ssl_error("Error loading X.509 certificates", result); return -1; } return 0; }
void gtget_ssl_connect(connection_t * conn) { int ret; sslparam_t *ssl = (sslparam_t *) conn->ssl; if (conn->proxy->host) proxy_connect(conn); ssl_set_bio(&ssl->ssl, net_recv, &conn->sockfd, net_send, &conn->sockfd); while ((ret = ssl_handshake(&ssl->ssl))) { if (ret != POLARSSL_ERR_NET_WANT_WRITE && ret != POLARSSL_ERR_NET_WANT_READ) break; } if (ret) { if (conn->verbosity >= 1) { write2f("ssl_handshake() @ %d returned %d, ", conn->sockfd, -ret); print_ssl_error(ret); } die(conn, "ssl_handshake() failed", NULL); } if (conn->verbosity >= 1) write2f(" => ssl_handshake OK. %s\n", ssl_get_ciphersuite(&ssl->ssl)); conn->read = gtget_ssl_read; conn->write = gtget_ssl_write; }
/** * Connect to a host using an encrypted stream */ BIO* connect_encrypted(char* host_and_port, char* store_path, char store_type, SSL_CTX** ctx, SSL** ssl) { BIO* bio = NULL; int r = 0; /* Set up the SSL pointers */ *ctx = SSL_CTX_new(SSLv23_client_method()); *ssl = NULL; /* Load the trust store from the pem location in argv[2] */ if (store_type == 'f') r = SSL_CTX_load_verify_locations(*ctx, store_path, NULL); else r = SSL_CTX_load_verify_locations(*ctx, NULL, store_path); if (r == 0) { print_ssl_error_2("Unable to load the trust store from %s.\n", store_path, stdout); return NULL; } /* Setting up the BIO SSL object */ bio = BIO_new_ssl_connect(*ctx); BIO_get_ssl(bio, ssl); if (!(*ssl)) { print_ssl_error("Unable to allocate SSL pointer.\n", stdout); return NULL; } SSL_set_mode(*ssl, SSL_MODE_AUTO_RETRY); /* Attempt to connect */ BIO_set_conn_hostname(bio, host_and_port); /* Verify the connection opened and perform the handshake */ if (BIO_do_connect(bio) < 1) { print_ssl_error_2("Unable to connect BIO.%s\n", host_and_port, stdout); return NULL; } if (SSL_get_verify_result(*ssl) != X509_V_OK) { print_ssl_error("Unable to verify connection result.\n", stdout); } return bio; }
static int shutdown_free_server_dtls (int pos) { int i, err; if (dtls_socket_tab[pos].ssl_type == 1) { if (dtls_socket_tab[pos].ssl_conn != NULL) { #ifdef SSLDEBUG OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO3, NULL, "DTLS server SSL_shutdown\n")); #endif i = SSL_shutdown (dtls_socket_tab[pos].ssl_conn); if (i <= 0) { err = SSL_get_error (dtls_socket_tab[pos].ssl_conn, i); print_ssl_error (err); #ifdef SSLDEBUG OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "DTLS server shutdown <= 0\n")); #endif } else { #ifdef SSLDEBUG OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO3, NULL, "DTLS server shutdown > 0\n")); #endif } SSL_free (dtls_socket_tab[pos].ssl_conn); #if 0 if (dtls_socket_tab[pos].ssl_ctx != NULL) SSL_CTX_free (dtls_socket_tab[pos].ssl_ctx); #endif memset (&(dtls_socket_tab[pos]), 0, sizeof (struct socket_tab)); return 0; } else { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "DTLS server shutdown: invalid SSL object!\n")); return -1; } } return -1; }
/** * Connect to a host using an unencrypted stream */ BIO* connect_unencrypted(char* host_and_port) { BIO* bio = NULL; /* Create a new connection */ bio = BIO_new_connect(host_and_port); if (bio == NULL) { print_ssl_error("Unable to create a new unencrypted BIO object.\n", stdout); return NULL; } /* Verify successful connection */ if (BIO_do_connect(bio) != 1) { print_ssl_error("Unable to connect unencrypted.\n", stdout); close_connection(bio); return NULL; } return bio; }
/* Load CA CRL from file */ int ssl_load_ca_crl(char *file, x509_crl **ca_crl) { int result; if (file == NULL) { return -1; } if ((*ca_crl = (x509_crl*)malloc(sizeof(x509_crl))) == NULL) { return -1; } memset(*ca_crl, 0, sizeof(x509_crl)); if ((result = x509parse_crlfile(*ca_crl, file)) != 0) { print_ssl_error("Error loading X.509 CA CRL", result); return -1; } return 0; }
/* Load CA certificate from file. */ int ssl_load_ca_cert(char *file, x509_cert **ca_certificate) { int result; if (file == NULL) { return -1; } if ((*ca_certificate = (x509_cert*)malloc(sizeof(x509_cert))) == NULL) { return -1; } memset(*ca_certificate, 0, sizeof(x509_cert)); if ((result = x509parse_crtfile(*ca_certificate, file)) != 0) { print_ssl_error("Error loading X.509 CA certificate", result); return -1; } return 0; }
/** * Write to a stream and handle restarts if nessecary */ int write_to_stream(BIO* bio, char* buffer, ssize_t length) { ssize_t r = -1; while (r < 0) { r = BIO_write(bio, buffer, length); if (r <= 0) { if (!BIO_should_retry(bio)) { print_ssl_error("BIO_read should retry test failed.\n", stdout); continue; } /* It would be prudent to check the reason for the retry and handle * it appropriately here */ } } return r; }
static int dtls_tl_send_message(osip_transaction_t * tr, osip_message_t * sip, char *host, int port, int out_socket) { int len = 0; size_t length = 0; struct addrinfo *addrinfo; struct __eXosip_sockaddr addr; char *message; char ipbuf[INET6_ADDRSTRLEN]; int i; int pos; struct socket_tab *socket_tab_used=NULL; BIO *sbio=NULL; if (dtls_socket <= 0) return -1; if (host == NULL) { host = sip->req_uri->host; if (sip->req_uri->port != NULL) port = osip_atoi (sip->req_uri->port); else port = 5061; } if (port == 5060) port = 5061; if (MSG_IS_REQUEST(sip)) { if (MSG_IS_REGISTER(sip) ||MSG_IS_INVITE(sip) ||MSG_IS_SUBSCRIBE(sip) || MSG_IS_NOTIFY(sip)) eXtl_update_local_target(sip); } i=-1; #ifndef MINISIZE if (tr!=NULL && tr->record.name[0]!='\0' && tr->record.srventry[0].srv[0]!='\0') { /* always choose the first here. if a network error occur, remove first entry and replace with next entries. */ osip_srv_entry_t *srv; int n=0; for (srv = &tr->record.srventry[0]; n<10 && tr->record.srventry[0].srv[0]; srv = &tr->record.srventry[0]) { i = eXosip_get_addrinfo (&addrinfo, srv->srv, srv->port, IPPROTO_UDP); if (i == 0) { host = srv->srv; port = srv->port; break; } memmove(&tr->record.srventry[0], &tr->record.srventry[1], 9*sizeof(osip_srv_entry_t)); memset(&tr->record.srventry[9], 0, sizeof(osip_srv_entry_t)); i=-1; /* copy next element */ n++; } } #endif /* if SRV was used, distination may be already found */ if (i != 0) { i = eXosip_get_addrinfo (&addrinfo, host, port, IPPROTO_UDP); } if (i != 0) { return -1; } memcpy (&addr, addrinfo->ai_addr, addrinfo->ai_addrlen); len = addrinfo->ai_addrlen; eXosip_freeaddrinfo (addrinfo); /* remove preloaded route if there is no tag in the To header */ { osip_route_t *route=NULL; osip_generic_param_t *tag=NULL; osip_message_get_route (sip, 0, &route); osip_to_get_tag (sip->to, &tag); if (tag==NULL && route != NULL && route->url != NULL) { osip_list_remove(&sip->routes, 0); } i = osip_message_to_str (sip, &message, &length); if (tag==NULL && route != NULL && route->url != NULL) { osip_list_add(&sip->routes, route, 0); } } if (i != 0 || length <= 0) { return -1; } switch ( ((struct sockaddr *)&addr)->sa_family ) { case AF_INET: inet_ntop (((struct sockaddr *)&addr)->sa_family, &(((struct sockaddr_in *) &addr)->sin_addr), ipbuf, sizeof (ipbuf)); break; case AF_INET6: inet_ntop (((struct sockaddr *)&addr)->sa_family, &(((struct sockaddr_in6 *) &addr)->sin6_addr), ipbuf, sizeof (ipbuf)); break; default: strncpy (ipbuf, "(unknown)", sizeof (ipbuf)); break; } OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "Message sent: \n%s (to dest=%s:%i)\n", message, ipbuf, port)); for (pos = 0; pos < EXOSIP_MAX_SOCKETS; pos++) { if (dtls_socket_tab[pos].ssl_conn != NULL && dtls_socket_tab[pos].ssl_type == EXOSIP_AS_A_SERVER) { if (dtls_socket_tab[pos].remote_port == port && (strcmp (dtls_socket_tab[pos].remote_ip, ipbuf) == 0)) { BIO *rbio; socket_tab_used = &dtls_socket_tab[pos]; rbio = BIO_new_dgram (dtls_socket, BIO_NOCLOSE); BIO_dgram_set_peer (rbio, &addr); dtls_socket_tab[pos].ssl_conn->rbio = rbio; break; } } } if (socket_tab_used==NULL) { for (pos = 0; pos < EXOSIP_MAX_SOCKETS; pos++) { if (dtls_socket_tab[pos].ssl_conn != NULL && dtls_socket_tab[pos].ssl_type == EXOSIP_AS_A_CLIENT) { if (dtls_socket_tab[pos].remote_port == port && (strcmp (dtls_socket_tab[pos].remote_ip, ipbuf) == 0)) { BIO *rbio; socket_tab_used = &dtls_socket_tab[pos]; rbio = BIO_new_dgram (dtls_socket, BIO_NOCLOSE); BIO_dgram_set_peer (rbio, &addr); dtls_socket_tab[pos].ssl_conn->rbio = rbio; break; } } } } if (socket_tab_used==NULL) { /* delete an old one! */ pos=0; if (dtls_socket_tab[pos].ssl_conn != NULL) { shutdown_free_client_dtls (pos); shutdown_free_server_dtls (pos); } memset(&dtls_socket_tab[pos], 0, sizeof(struct socket_tab)); } if (dtls_socket_tab[pos].ssl_conn == NULL) { /* create a new one */ SSL_CTX_set_read_ahead (client_ctx, 1); dtls_socket_tab[pos].ssl_conn = SSL_new (client_ctx); if (dtls_socket_tab[pos].ssl_conn == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "DTLS SSL_new error\n")); if (dtls_socket_tab[pos].ssl_conn != NULL) { shutdown_free_client_dtls (pos); shutdown_free_server_dtls (pos); } memset(&dtls_socket_tab[pos], 0, sizeof(struct socket_tab)); osip_free (message); return -1; } if (connect (dtls_socket, (struct sockaddr *) &addr, sizeof (addr)) == -1) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "DTLS connect error\n")); if (dtls_socket_tab[pos].ssl_conn != NULL) { shutdown_free_client_dtls (pos); shutdown_free_server_dtls (pos); } memset(&dtls_socket_tab[pos], 0, sizeof(struct socket_tab)); osip_free (message); return -1; } SSL_set_options (dtls_socket_tab[pos].ssl_conn, SSL_OP_NO_QUERY_MTU); SSL_set_mtu (dtls_socket_tab[pos].ssl_conn, 2000); SSL_set_connect_state (dtls_socket_tab[pos].ssl_conn); sbio = BIO_new_dgram (dtls_socket, BIO_NOCLOSE); BIO_ctrl_set_connected (sbio, 1, (struct sockaddr *) &addr); SSL_set_bio (dtls_socket_tab[pos].ssl_conn, sbio, sbio); dtls_socket_tab[pos].ssl_type = 2; dtls_socket_tab[pos].ssl_state = 2; osip_strncpy (dtls_socket_tab[pos].remote_ip, ipbuf, sizeof (dtls_socket_tab[pos].remote_ip)); dtls_socket_tab[pos].remote_port = port; } i = SSL_write (dtls_socket_tab[pos].ssl_conn, message, length); if (i<0) { i = SSL_get_error (dtls_socket_tab[pos].ssl_conn, i); print_ssl_error (i); if (i==SSL_ERROR_SSL || i==SSL_ERROR_SYSCALL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "DTLS SSL_write error\n")); if (dtls_socket_tab[pos].ssl_conn != NULL) { shutdown_free_client_dtls (pos); shutdown_free_server_dtls (pos); } memset(&dtls_socket_tab[pos], 0, sizeof(struct socket_tab)); } #ifndef MINISIZE /* delete first SRV entry that is not reachable */ if (tr->record.name[0]!='\0' && tr->record.srventry[0].srv[0]!='\0') { memmove(&tr->record.srventry[0], &tr->record.srventry[1], 9*sizeof(osip_srv_entry_t)); memset(&tr->record.srventry[9], 0, sizeof(osip_srv_entry_t)); osip_free (message); return 0; /* retry for next retransmission! */ } #endif /* SIP_NETWORK_ERROR; */ osip_free (message); return -1; } if (eXosip.keep_alive > 0) { if (MSG_IS_REGISTER (sip)) { eXosip_reg_t *reg = NULL; if (_eXosip_reg_find (®, tr) == 0) { memcpy (&(reg->addr), &addr, len); reg->len = len; } } } osip_free (message); return 0; }
static int dtls_tl_read_message(fd_set *osip_fdset) { char *enc_buf; char *dec_buf; int i; int enc_buf_len; if (dtls_socket<=0) return -1; if (FD_ISSET (dtls_socket, osip_fdset)) { struct sockaddr_storage sa; #ifdef __linux socklen_t slen; #else int slen; #endif if (eXtl_dtls.proto_family == AF_INET) slen = sizeof (struct sockaddr_in); else slen = sizeof (struct sockaddr_in6); enc_buf = (char *) osip_malloc (SIP_MESSAGE_MAX_LENGTH * sizeof (char) + 1); if (enc_buf==NULL) return -1; enc_buf_len = recvfrom (dtls_socket, enc_buf, SIP_MESSAGE_MAX_LENGTH, 0, (struct sockaddr *) &sa, &slen); if (enc_buf_len > 5) { char src6host[NI_MAXHOST]; int recvport = 0; int err; BIO *rbio; struct socket_tab *socket_tab_used=NULL; int pos; osip_strncpy (enc_buf + enc_buf_len, "\0", 1); OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "Received message: \n%s\n", enc_buf)); memset (src6host, 0, sizeof (src6host)); if (eXtl_dtls.proto_family == AF_INET) recvport = ntohs (((struct sockaddr_in *) &sa)->sin_port); else recvport = ntohs (((struct sockaddr_in6 *) &sa)->sin6_port); #if defined(__arc__) { struct sockaddr_in *fromsa = (struct sockaddr_in *) &sa; char *tmp; tmp = inet_ntoa(fromsa->sin_addr); if (tmp==NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Message received from: NULL:%i inet_ntoa failure\n", recvport)); } else { snprintf(src6host, sizeof(src6host), "%s", tmp); OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "Message received from: %s:%i\n", src6host, recvport)); } } #else err = getnameinfo ((struct sockaddr *) &sa, slen, src6host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); if (err != 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Message received from: NULL:%i getnameinfo failure\n", recvport)); snprintf(src6host, sizeof(src6host), "127.0.0.1"); } else { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "Message received from: %s:%i\n", src6host, recvport)); } #endif OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "Message received from: %s:%i\n", src6host, recvport)); for (pos = 0; pos < EXOSIP_MAX_SOCKETS; pos++) { if (dtls_socket_tab[pos].ssl_conn != NULL) { if (dtls_socket_tab[pos].remote_port == recvport && (strcmp (dtls_socket_tab[pos].remote_ip, src6host) == 0)) { socket_tab_used = &dtls_socket_tab[pos]; break; } } } if (socket_tab_used==NULL) { for (pos = 0; pos < EXOSIP_MAX_SOCKETS; pos++) { if (dtls_socket_tab[pos].ssl_conn == NULL) { /* should accept this connection? */ break; } } OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO3, NULL, "creating DTLS socket at index: %i\n", pos)); if (pos<0) { /* delete an old one! */ pos=0; if (dtls_socket_tab[pos].ssl_conn != NULL) { shutdown_free_client_dtls (pos); shutdown_free_server_dtls (pos); } memset(&dtls_socket_tab[pos], 0, sizeof(struct socket_tab)); } } if (dtls_socket_tab[pos].ssl_conn==NULL) { BIO *wbio; if (!SSL_CTX_check_private_key (server_ctx)) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "SSL CTX private key check error\n")); osip_free(enc_buf); return -1; } /* behave as a server: */ dtls_socket_tab[pos].ssl_conn = SSL_new (server_ctx); if (dtls_socket_tab[pos].ssl_conn == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "SSL_new error\n")); osip_free(enc_buf); return -1; } /* No MTU query */ SSL_set_options (dtls_socket_tab[pos].ssl_conn, SSL_OP_NO_QUERY_MTU); SSL_set_mtu (dtls_socket_tab[pos].ssl_conn, 2000); /* MTU query */ /* BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL); */ SSL_set_options (dtls_socket_tab[pos].ssl_conn, SSL_OP_COOKIE_EXCHANGE); wbio = BIO_new_dgram (dtls_socket, BIO_NOCLOSE); BIO_dgram_set_peer (wbio, &sa); SSL_set_bio (dtls_socket_tab[pos].ssl_conn, NULL, wbio); SSL_set_accept_state (dtls_socket_tab[pos].ssl_conn); dtls_socket_tab[pos].ssl_state = 0; dtls_socket_tab[pos].ssl_type = EXOSIP_AS_A_SERVER; osip_strncpy (dtls_socket_tab[pos].remote_ip, src6host, sizeof (dtls_socket_tab[pos].remote_ip)); dtls_socket_tab[pos].remote_port = recvport; OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "New DTLS connection accepted\n")); } dec_buf = (char *) osip_malloc (SIP_MESSAGE_MAX_LENGTH * sizeof (char) + 1); if (dec_buf==NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Allocation error\n")); osip_free(enc_buf); return -1; } rbio = BIO_new_mem_buf (enc_buf, enc_buf_len); BIO_set_mem_eof_return (rbio, -1); dtls_socket_tab[pos].ssl_conn->rbio = rbio; i = SSL_read (dtls_socket_tab[pos].ssl_conn, dec_buf, SIP_MESSAGE_MAX_LENGTH); /* done with the rbio */ BIO_free (dtls_socket_tab[pos].ssl_conn->rbio); dtls_socket_tab[pos].ssl_conn->rbio = BIO_new (BIO_s_mem ()); if (i > 5) { osip_strncpy (dec_buf + i, "\0", 1); _eXosip_handle_incoming_message(dec_buf, i, dtls_socket, src6host, recvport); } #ifndef MINISIZE else if (i <= 0) { err = SSL_get_error (dtls_socket_tab[pos].ssl_conn, i); print_ssl_error (err); if (err==SSL_ERROR_SYSCALL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "DTLS SYSCALL on SSL_read\n")); } else if (err==SSL_ERROR_SSL || err==SSL_ERROR_ZERO_RETURN) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "DTLS closed\n")); shutdown_free_client_dtls (pos); shutdown_free_server_dtls (pos); memset (&(dtls_socket_tab[pos]), 0, sizeof (dtls_socket_tab[pos])); } } else { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "Dummy SIP message received\n")); } #endif osip_free (dec_buf); osip_free (enc_buf); } } return 0; }
static int shutdown_free_client_dtls (int pos) { int i, err; BIO *rbio; struct addrinfo *addrinfo; struct __eXosip_sockaddr addr; if (dtls_socket_tab[pos].ssl_type == 2) { if (dtls_socket_tab[pos].ssl_conn != NULL) { i = eXosip_get_addrinfo (&addrinfo, dtls_socket_tab[pos].remote_ip, dtls_socket_tab[pos].remote_port, IPPROTO_UDP); if (i != 0) { return -1; } memcpy (&addr, addrinfo->ai_addr, addrinfo->ai_addrlen); eXosip_freeaddrinfo (addrinfo); rbio = BIO_new_dgram (dtls_socket, BIO_NOCLOSE); BIO_dgram_set_peer (rbio, &addr); (dtls_socket_tab[pos].ssl_conn)->rbio = rbio; i = SSL_shutdown (dtls_socket_tab[pos].ssl_conn); if (i <= 0) { err = SSL_get_error (dtls_socket_tab[pos].ssl_conn, i); #ifdef SSLDEBUG OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "DTLS client shutdown error %d <= 0\n", i)); #endif print_ssl_error (err); } else { #ifdef SSLDEBUG OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO3, NULL, "DTLS client shutdown > 0\n")); #endif } SSL_free (dtls_socket_tab[pos].ssl_conn); #if 0 if (dtls_socket_tab[pos].ssl_ctx != NULL) SSL_CTX_free (dtls_socket_tab[pos].ssl_ctx); #endif memset (&(dtls_socket_tab[pos]), 0, sizeof (struct socket_tab)); return 0; } else { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "DTLS client shutdown: invalid SSL object!\n")); return -1; } } return -1; }