PR: 2506
[openssl.git] / ssl / d1_lib.c
index 8039740555f2b388168a3250a277da20e237a62d..fafc5c0bc63a5dd0e6bca874b4d6131b1e5f55ff 100644 (file)
 #include <openssl/objects.h>
 #include "ssl_locl.h"
 
 #include <openssl/objects.h>
 #include "ssl_locl.h"
 
-#ifdef OPENSSL_SYS_WIN32
+#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS)
 #include <sys/timeb.h>
 #endif
 
 static void get_current_time(struct timeval *t);
 const char dtls1_version_str[]="DTLSv1" OPENSSL_VERSION_PTEXT;
 #include <sys/timeb.h>
 #endif
 
 static void get_current_time(struct timeval *t);
 const char dtls1_version_str[]="DTLSv1" OPENSSL_VERSION_PTEXT;
+int dtls1_listen(SSL *s, struct sockaddr *client);
 
 SSL3_ENC_METHOD DTLSv1_enc_data={
     dtls1_enc,
 
 SSL3_ENC_METHOD DTLSv1_enc_data={
     dtls1_enc,
@@ -128,26 +129,22 @@ int dtls1_new(SSL *s)
        return(1);
        }
 
        return(1);
        }
 
-void dtls1_free(SSL *s)
+static void dtls1_clear_queues(SSL *s)
        {
     pitem *item = NULL;
     hm_fragment *frag = NULL;
        {
     pitem *item = NULL;
     hm_fragment *frag = NULL;
-
-       ssl3_free(s);
-
+       
     while( (item = pqueue_pop(s->d1->unprocessed_rcds.q)) != NULL)
         {
         OPENSSL_free(item->data);
         pitem_free(item);
         }
     while( (item = pqueue_pop(s->d1->unprocessed_rcds.q)) != NULL)
         {
         OPENSSL_free(item->data);
         pitem_free(item);
         }
-    pqueue_free(s->d1->unprocessed_rcds.q);
 
     while( (item = pqueue_pop(s->d1->processed_rcds.q)) != NULL)
         {
         OPENSSL_free(item->data);
         pitem_free(item);
         }
 
     while( (item = pqueue_pop(s->d1->processed_rcds.q)) != NULL)
         {
         OPENSSL_free(item->data);
         pitem_free(item);
         }
-    pqueue_free(s->d1->processed_rcds.q);
 
     while( (item = pqueue_pop(s->d1->buffered_messages)) != NULL)
         {
 
     while( (item = pqueue_pop(s->d1->buffered_messages)) != NULL)
         {
@@ -156,7 +153,6 @@ void dtls1_free(SSL *s)
         OPENSSL_free(frag);
         pitem_free(item);
         }
         OPENSSL_free(frag);
         pitem_free(item);
         }
-    pqueue_free(s->d1->buffered_messages);
 
     while ( (item = pqueue_pop(s->d1->sent_messages)) != NULL)
         {
 
     while ( (item = pqueue_pop(s->d1->sent_messages)) != NULL)
         {
@@ -165,7 +161,6 @@ void dtls1_free(SSL *s)
         OPENSSL_free(frag);
         pitem_free(item);
         }
         OPENSSL_free(frag);
         pitem_free(item);
         }
-       pqueue_free(s->d1->sent_messages);
 
        while ( (item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL)
                {
 
        while ( (item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL)
                {
@@ -174,6 +169,18 @@ void dtls1_free(SSL *s)
                OPENSSL_free(frag);
                pitem_free(item);
                }
                OPENSSL_free(frag);
                pitem_free(item);
                }
+       }
+
+void dtls1_free(SSL *s)
+       {
+       ssl3_free(s);
+
+       dtls1_clear_queues(s);
+
+    pqueue_free(s->d1->unprocessed_rcds.q);
+    pqueue_free(s->d1->processed_rcds.q);
+    pqueue_free(s->d1->buffered_messages);
+       pqueue_free(s->d1->sent_messages);
        pqueue_free(s->d1->buffered_app_data.q);
 
        OPENSSL_free(s->d1);
        pqueue_free(s->d1->buffered_app_data.q);
 
        OPENSSL_free(s->d1);
@@ -181,6 +188,36 @@ void dtls1_free(SSL *s)
 
 void dtls1_clear(SSL *s)
        {
 
 void dtls1_clear(SSL *s)
        {
+    pqueue unprocessed_rcds;
+    pqueue processed_rcds;
+    pqueue buffered_messages;
+       pqueue sent_messages;
+       pqueue buffered_app_data;
+       
+       if (s->d1)
+               {
+               unprocessed_rcds = s->d1->unprocessed_rcds.q;
+               processed_rcds = s->d1->processed_rcds.q;
+               buffered_messages = s->d1->buffered_messages;
+               sent_messages = s->d1->sent_messages;
+               buffered_app_data = s->d1->buffered_app_data.q;
+
+               dtls1_clear_queues(s);
+
+               memset(s->d1, 0, sizeof(*(s->d1)));
+
+               if (s->server)
+                       {
+                       s->d1->cookie_len = sizeof(s->d1->cookie);
+                       }
+
+               s->d1->unprocessed_rcds.q = unprocessed_rcds;
+               s->d1->processed_rcds.q = processed_rcds;
+               s->d1->buffered_messages = buffered_messages;
+               s->d1->sent_messages = sent_messages;
+               s->d1->buffered_app_data.q = buffered_app_data;
+               }
+
        ssl3_clear(s);
        if (s->options & SSL_OP_CISCO_ANYCONNECT)
                s->version=DTLS1_BAD_VER;
        ssl3_clear(s);
        if (s->options & SSL_OP_CISCO_ANYCONNECT)
                s->version=DTLS1_BAD_VER;
@@ -203,6 +240,9 @@ long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg)
        case DTLS_CTRL_HANDLE_TIMEOUT:
                ret = dtls1_handle_timeout(s);
                break;
        case DTLS_CTRL_HANDLE_TIMEOUT:
                ret = dtls1_handle_timeout(s);
                break;
+       case DTLS_CTRL_LISTEN:
+               ret = dtls1_listen(s, parg);
+               break;
 
        default:
                ret = ssl3_ctrl(s, cmd, larg, parg);
 
        default:
                ret = ssl3_ctrl(s, cmd, larg, parg);
@@ -279,6 +319,16 @@ struct timeval* dtls1_get_timeout(SSL *s, struct timeval* timeleft)
                timeleft->tv_usec += 1000000;
                }
 
                timeleft->tv_usec += 1000000;
                }
 
+       /* If remaining time is less than 15 ms, set it to 0
+        * to prevent issues because of small devergences with
+        * socket timeouts.
+        */
+       if (timeleft->tv_sec == 0 && timeleft->tv_usec < 15000)
+               {
+               memset(timeleft, 0, sizeof(struct timeval));
+               }
+       
+
        return timeleft;
        }
 
        return timeleft;
        }
 
@@ -316,6 +366,8 @@ void dtls1_stop_timer(SSL *s)
        memset(&(s->d1->next_timeout), 0, sizeof(struct timeval));
        s->d1->timeout_duration = 1;
        BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, &(s->d1->next_timeout));
        memset(&(s->d1->next_timeout), 0, sizeof(struct timeval));
        s->d1->timeout_duration = 1;
        BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, &(s->d1->next_timeout));
+       /* Clear retransmission buffer */
+       dtls1_clear_record_buffer(s);
        }
 
 int dtls1_handle_timeout(SSL *s)
        }
 
 int dtls1_handle_timeout(SSL *s)
@@ -334,7 +386,7 @@ int dtls1_handle_timeout(SSL *s)
        if ( state->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT)
                {
                /* fail the connection, enough alerts have been sent */
        if ( state->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT)
                {
                /* fail the connection, enough alerts have been sent */
-               SSLerr(SSL_F_DTLS1_READ_FAILED,SSL_R_READ_TIMEOUT_EXPIRED);
+               SSLerr(SSL_F_DTLS1_HANDLE_TIMEOUT,SSL_R_READ_TIMEOUT_EXPIRED);
                return 0;
                }
 
                return 0;
                }
 
@@ -364,3 +416,17 @@ static void get_current_time(struct timeval *t)
        gettimeofday(t, NULL);
 #endif
 }
        gettimeofday(t, NULL);
 #endif
 }
+
+int dtls1_listen(SSL *s, struct sockaddr *client)
+       {
+       int ret;
+
+       SSL_set_options(s, SSL_OP_COOKIE_EXCHANGE);
+       s->d1->listen = 1;
+
+       ret = SSL_accept(s);
+       if (ret <= 0) return ret;
+       
+       (void) BIO_dgram_get_peer(SSL_get_rbio(s), client);
+       return 1;
+       }