gnutls-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU gnutls branch, master, updated. gnutls_2_11_6-327-g67f4dba


From: Nikos Mavrogiannopoulos
Subject: [SCM] GNU gnutls branch, master, updated. gnutls_2_11_6-327-g67f4dba
Date: Sun, 20 Mar 2011 13:25:10 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU gnutls".

http://git.savannah.gnu.org/cgit/gnutls.git/commit/?id=67f4dba6e394b599a1958db8d5c414d401e43382

The branch, master has been updated
       via  67f4dba6e394b599a1958db8d5c414d401e43382 (commit)
       via  84e265447ef5f6cada0db92b9f475ab83c2f25a9 (commit)
      from  0ce9d5617e88824df394b56f00317643bee24efc (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 67f4dba6e394b599a1958db8d5c414d401e43382
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sun Mar 20 14:18:57 2011 +0100

    Avoided waiting for peer's retransmission to ensure receipt of finished 
messages, and used a 'timer'-like to retransmit packets.

commit 84e265447ef5f6cada0db92b9f475ab83c2f25a9
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sun Mar 20 11:06:53 2011 +0100

    added gnutls_dtls_get_data_mtu().

-----------------------------------------------------------------------

Summary of changes:
 lib/gnutls_buffers.c            |   14 ++++--
 lib/gnutls_buffers.h            |    2 +-
 lib/gnutls_dtls.c               |   85 ++++++++++++++++++++++++++-------------
 lib/gnutls_dtls.h               |   66 ++++++++++++++++++++++++++++++
 lib/gnutls_handshake.c          |   11 +++++-
 lib/gnutls_handshake.h          |    5 ++
 lib/gnutls_int.h                |    8 ++++
 lib/gnutls_record.c             |   78 ++++++++++++++++++++++++------------
 lib/includes/gnutls/dtls.h      |    2 +
 lib/includes/gnutls/gnutls.h.in |    2 +-
 lib/libgnutls.map               |    1 +
 lib/system.c                    |   26 ++----------
 lib/system.h                    |    2 +-
 src/cli.c                       |   11 +++++
 src/common.h                    |    1 +
 src/serv.c                      |   11 +++++-
 src/udp-serv.c                  |   12 +----
 17 files changed, 243 insertions(+), 94 deletions(-)

diff --git a/lib/gnutls_buffers.c b/lib/gnutls_buffers.c
index 31e56b5..778af8d 100644
--- a/lib/gnutls_buffers.c
+++ b/lib/gnutls_buffers.c
@@ -600,7 +600,7 @@ _gnutls_io_write_flush (gnutls_session_t session)
  * on timeout and a negative value on error.
  */
 int
-_gnutls_io_check_recv (gnutls_session_t session, void* data, size_t data_size, 
unsigned int ms)
+_gnutls_io_check_recv (gnutls_session_t session, unsigned int ms)
 {
   gnutls_transport_ptr_t fd = session->internals.transport_send_ptr;
   int ret = 0;
@@ -609,7 +609,7 @@ _gnutls_io_check_recv (gnutls_session_t session, void* 
data, size_t data_size, u
     session->internals.pull_func != system_read)
     return gnutls_assert_val(GNUTLS_E_PULL_ERROR);
 
-  ret = session->internals.pull_timeout_func(fd, data, data_size, ms);
+  ret = session->internals.pull_timeout_func(fd, ms);
   if (ret == -1)
     return gnutls_assert_val(GNUTLS_E_PULL_ERROR);
   
@@ -740,6 +740,8 @@ parse_handshake_header (gnutls_session_t session, 
mbuffer_st* bufel, gnutls_hand
     return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
 
   dataptr = _mbuffer_get_udata_ptr(bufel);
+  data_size = _mbuffer_get_udata_size(bufel) - handshake_header_size;
+
   /* if reading a client hello of SSLv2 */
   if (!IS_DTLS(session) && htype == GNUTLS_HANDSHAKE_CLIENT_HELLO &&
     bufel->htype == GNUTLS_HANDSHAKE_CLIENT_HELLO_V2)
@@ -785,14 +787,16 @@ parse_handshake_header (gnutls_session_t session, 
mbuffer_st* bufel, gnutls_hand
   /* make the length offset */
   if (hsk->end_offset > 0) hsk->end_offset--;
 
-  _gnutls_handshake_log ("HSK[%p]: %s was received. Length %d, frag offset %d, 
frag length: %d, sequence: %d\n",
+  _gnutls_handshake_log ("HSK[%p]: %s was received. Length %d[%d], frag offset 
%d, frag length: %d, sequence: %d\n",
                          session, _gnutls_handshake2str (hsk->htype),
-                         (int) hsk->length, hsk->start_offset, 
hsk->end_offset-hsk->start_offset+1, (int)hsk->sequence);
+                         (int) hsk->length, (int)data_size, hsk->start_offset, 
hsk->end_offset-hsk->start_offset+1, (int)hsk->sequence);
 
   hsk->header_size = handshake_header_size;
   memcpy(hsk->header, _mbuffer_get_udata_ptr(bufel), handshake_header_size);
 
-  data_size = _mbuffer_get_udata_size(bufel) - handshake_header_size;
+  if (hsk->length > 0 && 
+        (hsk->end_offset-hsk->start_offset >=  data_size))
+    return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
 
   if (hsk->length > 0 && (hsk->start_offset >= hsk->end_offset ||
       hsk->end_offset-hsk->start_offset >=  data_size ||
diff --git a/lib/gnutls_buffers.h b/lib/gnutls_buffers.h
index 60d2e64..bc432bd 100644
--- a/lib/gnutls_buffers.h
+++ b/lib/gnutls_buffers.h
@@ -79,7 +79,7 @@ _gnutls_handshake_io_recv_int (gnutls_session_t session,
 
 ssize_t _gnutls_io_write_flush (gnutls_session_t session);
 int
-_gnutls_io_check_recv (gnutls_session_t session, void* data, size_t data_size, 
unsigned int ms);
+_gnutls_io_check_recv (gnutls_session_t session, unsigned int ms);
 ssize_t _gnutls_handshake_io_write_flush (gnutls_session_t session);
 
 inline static void _gnutls_handshake_buffer_clear(handshake_buffer_st* hsk)
diff --git a/lib/gnutls_dtls.c b/lib/gnutls_dtls.c
index 9a5771e..076be8c 100644
--- a/lib/gnutls_dtls.c
+++ b/lib/gnutls_dtls.c
@@ -46,7 +46,7 @@ transmit_message (gnutls_session_t session,
   opaque *data, *mtu_data;
   int ret = 0;
   unsigned int offset, frag_len, data_size;
-  const uint mtu = gnutls_dtls_get_mtu(session) - DTLS_HANDSHAKE_HEADER_SIZE;
+  const uint mtu = gnutls_dtls_get_data_mtu(session) - 
DTLS_HANDSHAKE_HEADER_SIZE;
 
   if (bufel->type == GNUTLS_CHANGE_CIPHER_SPEC)
     {
@@ -104,14 +104,13 @@ transmit_message (gnutls_session_t session,
                        _gnutls_handshake2str (bufel->htype),
                        bufel->htype, data_size, offset, frag_len);
 
-      /* FIXME: We should collaborate with the record layer to pack as
-       * many records possible into a single datagram. We should also
-       * tell the record layer which epoch to use for encryption. 
-       */
       ret = _gnutls_send_int (session, bufel->type, bufel->htype, 
         bufel->epoch, mtu_data, DTLS_HANDSHAKE_HEADER_SIZE + frag_len, 0);
       if (ret < 0)
-        break;
+        {
+          gnutls_assert();
+          break;
+        }
    }
 
   gnutls_free (mtu_data);
@@ -119,11 +118,9 @@ transmit_message (gnutls_session_t session,
   return ret;
 }
 
-static int drop_usage_count(gnutls_session_t session)
+static int drop_usage_count(gnutls_session_t session, mbuffer_head_st *const 
send_buffer)
 {
   int ret;
-  mbuffer_head_st *const send_buffer =
-    &session->internals.handshake_send_buffer;
   mbuffer_st *cur;
 
   for (cur = send_buffer->head;
@@ -137,8 +134,26 @@ static int drop_usage_count(gnutls_session_t session)
   return 0;
 }
 
-#define MAX_TIMEOUT 60000
-#define FINISHED_TIMEOUT 3000
+#define RETRANSMIT_WINDOW 2
+
+/* This function is to be called from record layer once
+ * a handshake replay is detected. It will make sure
+ * it transmits only once per few seconds. Otherwise
+ * it is the same as _dtls_transmit().
+ */
+int _dtls_retransmit(gnutls_session_t session)
+{
+time_t now = time(0);
+
+  if (now - session->internals.dtls.last_retransmit > RETRANSMIT_WINDOW)
+    {
+      session->internals.dtls.last_retransmit = now;
+      return _dtls_transmit(session);
+    }
+  else
+    return 0;
+
+}
 
 /* This function transmits the flight that has been previously
  * buffered.
@@ -175,28 +190,22 @@ int ret;
         return gnutls_assert_val(ret);
 
       /* last message in handshake -> no ack */
-      if (last_type == GNUTLS_HANDSHAKE_FINISHED &&
-        ((session->security_parameters.entity == GNUTLS_SERVER && 
session->internals.resumed == RESUME_FALSE) ||
-         (session->security_parameters.entity == GNUTLS_CLIENT && 
session->internals.resumed == RESUME_TRUE)))
+      if (last_type == GNUTLS_HANDSHAKE_FINISHED && _dtls_is_async(session))
         {
-          opaque c;
-          ret = _gnutls_io_check_recv(session, &c, 1, FINISHED_TIMEOUT);
-          if (ret == GNUTLS_E_TIMEDOUT)
-            ret = 0;
-          else if (ret >= 0)
-            {
-              if (c == GNUTLS_HANDSHAKE) /* retransmit */
-                ret = GNUTLS_E_TIMEDOUT;
-            }
+          /* we cannot do anything here. We just return 0 and
+           * if a retransmission occurs because peer didn't receive it
+           * we rely on the record layer calling this function again.
+           */
+          return 0;
         }
       else /* all other messages -> implicit ack (receive of next flight) */
         {
-          ret = _gnutls_io_check_recv(session, NULL, 0, timeout);
+          ret = _gnutls_io_check_recv(session, timeout);
         }
 
       total_timeout += timeout;
       timeout *= 2;
-      timeout %= MAX_TIMEOUT;
+      timeout %= MAX_DTLS_TIMEOUT;
 
       if (total_timeout >= session->internals.dtls.total_timeout) {
         ret = gnutls_assert_val(GNUTLS_E_TIMEDOUT);
@@ -214,7 +223,7 @@ int ret;
   ret = 0;
 
 cleanup:
-  drop_usage_count(session);
+  drop_usage_count(session, send_buffer);
   _mbuffer_head_clear(send_buffer);
 
   /* SENDING -> WAITING state transition */
@@ -333,6 +342,9 @@ int i, offset = 0;
  * be retransmitted. The total timeout is the time after which the
  * handshake will be aborted with %GNUTLS_E_TIMEDOUT.
  *
+ * The DTLS protocol recommends the values of 1 sec and 60 seconds
+ * respectively.
+ *
  * If the retransmission timeout is zero then the handshake will operate
  * in a non-blocking way, i.e., return %GNUTLS_E_AGAIN.
  *
@@ -359,7 +371,7 @@ void gnutls_dtls_set_mtu (gnutls_session_t session, 
unsigned int mtu)
 }
 
 /**
- * gnutls_dtls_get_mtu:
+ * gnutls_dtls_get_data_mtu:
  * @session: is a #gnutls_session_t structure.
  *
  * This function will return the actual maximum transfer unit for
@@ -369,7 +381,7 @@ void gnutls_dtls_set_mtu (gnutls_session_t session, 
unsigned int mtu)
  * Returns: the maximum allowed transfer unit.
  *
  **/
-unsigned int gnutls_dtls_get_mtu (gnutls_session_t session)
+unsigned int gnutls_dtls_get_data_mtu (gnutls_session_t session)
 {
 int ret;
 
@@ -380,6 +392,23 @@ int ret;
     return session->internals.dtls.mtu - RECORD_HEADER_SIZE(session);
 }
 
+/**
+ * gnutls_dtls_get_mtu:
+ * @session: is a #gnutls_session_t structure.
+ *
+ * This function will return the MTU size as set with
+ * gnutls_dtls_set_mtu(). This is not the actual MTU
+ * of data you can transmit. Use gnutls_dtls_get_data_mtu()
+ * for that reason.
+ *
+ * Returns: the set maximum transfer unit.
+ *
+ **/
+unsigned int gnutls_dtls_get_mtu (gnutls_session_t session)
+{
+  return session->internals.dtls.mtu;
+}
+
 #define COOKIE_SIZE 16
 #define COOKIE_MAC_SIZE 16
 
diff --git a/lib/gnutls_dtls.h b/lib/gnutls_dtls.h
index ab4e4da..f8436b3 100644
--- a/lib/gnutls_dtls.h
+++ b/lib/gnutls_dtls.h
@@ -26,8 +26,74 @@
 # define DTLS_H
 
 #include "gnutls_int.h"
+#include "gnutls_buffers.h"
+#include "gnutls_mbuffers.h"
 
 int _dtls_transmit(gnutls_session_t session);
+int _dtls_retransmit(gnutls_session_t session);
 int _dtls_record_check(gnutls_session_t session, uint64 * _seq);
 
+#define MAX_DTLS_TIMEOUT 60000
+
+/* returns true or false depending on whether we need to
+ * handle asynchronously handshake data.
+ */
+inline static int _dtls_is_async(gnutls_session_t session)
+{
+  if ((session->security_parameters.entity == GNUTLS_SERVER && 
session->internals.resumed == RESUME_FALSE) ||
+         (session->security_parameters.entity == GNUTLS_CLIENT && 
session->internals.resumed == RESUME_TRUE))
+    return 1;
+  else
+    return 0;
+}
+
+inline static void _dtls_async_timer_init(gnutls_session_t session)
+{
+  if (_dtls_is_async(session))
+    {
+      _gnutls_dtls_log ("DTLS[%p]: Initializing timer for handshake state.\n", 
session);
+      session->internals.dtls.async_term = time(0) + MAX_DTLS_TIMEOUT/1000;
+    }
+  else
+    session->internals.dtls.async_term = 0;
+}
+
+inline static void _dtls_async_timer_delete(gnutls_session_t session)
+{
+  if (session->internals.dtls.async_term != 0)
+    {
+      _gnutls_dtls_log ("DTLS[%p]: Deinitializing handshake state.\n", 
session);
+      _gnutls_handshake_io_buffer_clear (session);
+      session->internals.dtls.async_term = 0; /* turn off "timer" */
+    }
+}
+
+/* Checks whether it is time to terminate the timer
+ */
+inline static void _dtls_async_timer_check(gnutls_session_t session)
+{
+  if (!IS_DTLS(session))
+    return;
+
+  if (session->internals.dtls.async_term != 0)
+    {
+      time_t now = time(0);
+      
+      /* check if we need to expire the queued handshake data */
+      if (now > session->internals.dtls.async_term)
+        {
+          _dtls_async_timer_delete(session);
+        }
+    }
+}
+
+/* Returns non-zero if the async timer is active */
+inline static int _dtls_async_timer_active(gnutls_session_t session)
+{
+  if (!IS_DTLS(session))
+    return 0;
+
+  return session->internals.dtls.async_term;
+}
+
 #endif
diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c
index 7e0608d..fb4c3c2 100644
--- a/lib/gnutls_handshake.c
+++ b/lib/gnutls_handshake.c
@@ -56,6 +56,7 @@
 #include <auth_anon.h>          /* for gnutls_anon_server_credentials_t */
 #include <auth_psk.h>           /* for gnutls_psk_server_credentials_t */
 #include <random.h>
+#include <gnutls_dtls.h>
 
 #ifdef HANDSHAKE_DEBUG
 #define ERR(x, y) _gnutls_handshake_log("HSK[%p]: %s (%d)\n", session, x,y)
@@ -2603,7 +2604,15 @@ gnutls_handshake (gnutls_session_t session)
 
   STATE = STATE0;
 
-  _gnutls_handshake_io_buffer_clear (session);
+  if (IS_DTLS(session)==0)
+    {
+      _gnutls_handshake_io_buffer_clear (session);
+    }
+  else
+    {
+      _dtls_async_timer_init(session);
+    }
+
   _gnutls_handshake_internal_state_clear (session);
 
   session->security_parameters.epoch_next++;
diff --git a/lib/gnutls_handshake.h b/lib/gnutls_handshake.h
index 6792bbe..656c909 100644
--- a/lib/gnutls_handshake.h
+++ b/lib/gnutls_handshake.h
@@ -23,6 +23,9 @@
  *
  */
 
+#ifndef HANDSHAKE_H
+#define HANDSHAKE_H
+
 typedef enum Optional
 { OPTIONAL_PACKET, MANDATORY_PACKET } optional_t;
 
@@ -63,3 +66,5 @@ void _gnutls_handshake_hash_buffers_clear (gnutls_session_t 
session);
  */
 #define AGAIN(target) (STATE==target?1:0)
 #define AGAIN2(state, target) (state==target?1:0)
+
+#endif
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index 1c18817..4884888 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -593,6 +593,14 @@ typedef struct
   
   uint64_t record_sw[DTLS_RECORD_WINDOW_SIZE];
   int record_sw_size;
+  
+  /* timers to handle async handshake after gnutls_handshake()
+   * has terminated. Required to handle retransmissions.
+   */
+  time_t async_term;
+  
+  /* last retransmission triggered by record layer */
+  time_t last_retransmit;
 } dtls_st;
 
 
diff --git a/lib/gnutls_record.c b/lib/gnutls_record.c
index cc259c4..19f6aa3 100644
--- a/lib/gnutls_record.c
+++ b/lib/gnutls_record.c
@@ -48,6 +48,19 @@
 #include <gnutls_dtls.h>
 #include <gnutls_dh.h>
 
+struct tls_record_st {
+  uint16_t header_size;
+  uint8_t version[2];
+  uint64 sequence; /* DTLS */
+  uint16_t length;
+  uint16_t packet_size; /* header_size + length */
+  content_type_t type;
+  uint16_t epoch; /* valid in DTLS only */
+  int v2:1; /* whether an SSLv2 client hello */
+  /* the data */
+};
+
+
 /**
  * gnutls_protocol_get_version:
  * @session: is a #gnutls_session_t structure.
@@ -578,7 +591,7 @@ record_check_version (gnutls_session_t session,
  */
 static int
 record_add_to_buffers (gnutls_session_t session,
-                   content_type_t recv_type, content_type_t type,
+                   struct tls_record_st *recv, content_type_t type,
                    gnutls_handshake_description_t htype, 
                    uint64* seq,
                    mbuffer_st* bufel)
@@ -586,18 +599,22 @@ record_add_to_buffers (gnutls_session_t session,
 
   int ret;
 
-  if ((recv_type == type)
+  if ((recv->type == type)
       && (type == GNUTLS_APPLICATION_DATA ||
           type == GNUTLS_CHANGE_CIPHER_SPEC ||
           type == GNUTLS_HANDSHAKE))
     {
       _gnutls_record_buffer_put (session, type, seq, bufel);
+      
+      /* if we received application data as expected then we
+       * deactivate the async timer */
+      _dtls_async_timer_delete(session);
     }
   else
     {
       /* if the expected type is different than the received 
        */
-      switch (recv_type)
+      switch (recv->type)
         {
         case GNUTLS_ALERT:
           if (bufel->msg.size < 2)
@@ -651,9 +668,15 @@ record_add_to_buffers (gnutls_session_t session,
           return GNUTLS_E_UNEXPECTED_PACKET;
 
         case GNUTLS_APPLICATION_DATA:
+          if (session->internals.initial_negotiation_completed == 0)
+            {
+              ret = gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);
+              goto cleanup;
+            }
+
           /* even if data is unexpected put it into the buffer */
           if ((ret =
-               _gnutls_record_buffer_put (session, recv_type, seq,
+               _gnutls_record_buffer_put (session, recv->type, seq,
                                           bufel)) < 0)
             {
               gnutls_assert ();
@@ -678,6 +701,15 @@ record_add_to_buffers (gnutls_session_t session,
 
           break;
         case GNUTLS_HANDSHAKE:
+          /* In DTLS we might receive a handshake replay from the peer to 
indicate
+           * the our last TLS handshake messages were not received.
+           */
+          if (_dtls_is_async(session) && _dtls_async_timer_active(session))
+            {
+              ret = _dtls_retransmit(session);
+              goto cleanup;
+            }
+          
           /* This is legal if HELLO_REQUEST is received - and we are a client.
            * If we are a server, a client may initiate a renegotiation at any 
time.
            */
@@ -685,7 +717,7 @@ record_add_to_buffers (gnutls_session_t session,
             {
               gnutls_assert ();
               ret =
-                _gnutls_record_buffer_put (session, recv_type, seq, bufel);
+                _gnutls_record_buffer_put (session, recv->type, seq, bufel);
               if (ret < 0)
                 {
                   gnutls_assert ();
@@ -708,7 +740,7 @@ record_add_to_buffers (gnutls_session_t session,
 
           _gnutls_record_log
             ("REC[%p]: Received Unknown packet %d expecting %d\n",
-             session, recv_type, type);
+             session, recv->type, type);
 
           gnutls_assert ();
           ret = GNUTLS_E_INTERNAL_ERROR;
@@ -737,17 +769,6 @@ int ret;
   return ret;
 }
 
-struct tls_record_st {
-  uint16_t header_size;
-  uint8_t version[2];
-  uint64 sequence; /* DTLS */
-  uint16_t length;
-  uint16_t packet_size; /* header_size + length */
-  content_type_t type;
-  int v2:1; /* whether an SSLv2 client hello */
-  /* the data */
-};
-
 /* Checks the record headers and returns the length, version and
  * content type.
  */
@@ -784,6 +805,7 @@ record_read_headers (gnutls_session_t session,
        * V2 compatibility is a mess.
        */
       record->v2 = 1;
+      record->epoch = 0;
 
       _gnutls_record_log ("REC[%p]: SSL 2.0 %s packet received. Length: %d\n",
                           session, 
@@ -799,14 +821,18 @@ record_read_headers (gnutls_session_t session,
       record->type = headers[0];
       record->version[0] = headers[1];
       record->version[1] = headers[2];
-
+      
       if(IS_DTLS(session))
         {
           memcpy(record->sequence.i, &headers[3], 8);
           record->length = _gnutls_read_uint16 (&headers[11]);
+          record->epoch = _gnutls_read_uint16(record->sequence.i);
         }
       else
-        record->length = _gnutls_read_uint16 (&headers[3]);
+        {
+          record->length = _gnutls_read_uint16 (&headers[3]);
+          record->epoch = 0;
+        }
 
       _gnutls_record_log ("REC[%p]: SSL %d.%d %s packet received. Length: 
%d\n",
                           session, (int)record->version[0], 
(int)record->version[1], 
@@ -850,9 +876,7 @@ gnutls_datum_t raw; /* raw headers */
   /* Check if the DTLS epoch is valid */
   if (IS_DTLS(session)) 
     {
-      uint16_t epoch = _gnutls_read_uint16(record->sequence.i);
-      
-      if (_gnutls_epoch_is_valid(session, epoch) == 0)
+      if (_gnutls_epoch_is_valid(session, record->epoch) == 0)
         {
           _gnutls_audit_log("Discarded message[%u] with invalid epoch 
0x%.2x%.2x.\n",
             (unsigned int)_gnutls_uint64touint32 (&record->sequence), 
(int)record->sequence.i[0], 
@@ -1049,7 +1073,7 @@ begin:
     decrypted->htype = -1;
 
   ret =
-    record_add_to_buffers (session, record.type, type, htype, 
+    record_add_to_buffers (session, &record, type, htype, 
       packet_sequence, decrypted);
 
   /* bufel is now either deinitialized or buffered somewhere else */
@@ -1142,6 +1166,8 @@ _gnutls_recv_int (gnutls_session_t session, 
content_type_t type,
       return GNUTLS_E_INVALID_SESSION;
     }
 
+  _dtls_async_timer_check(session);
+  
   /* If we have enough data in the cache do not bother receiving
    * a new packet. (in order to flush the cache)
    */
@@ -1220,9 +1246,9 @@ gnutls_record_send (gnutls_session_t session, const void 
*data,
  * initiated a handshake. In that case the server can only initiate a
  * handshake or terminate the connection.
  *
- * Returns: the number of bytes received and zero on EOF.  A negative
- *   error code is returned in case of an error.  The number of bytes
- *   received might be less than @data_size.
+ * Returns: the number of bytes received and zero on EOF (for stream
+ * connections).  A negative error code is returned in case of an error.  
+ * The number of bytes received might be less than the requested @data_size.
  **/
 ssize_t
 gnutls_record_recv (gnutls_session_t session, void *data, size_t data_size)
diff --git a/lib/includes/gnutls/dtls.h b/lib/includes/gnutls/dtls.h
index 89d0388..39cb52d 100644
--- a/lib/includes/gnutls/dtls.h
+++ b/lib/includes/gnutls/dtls.h
@@ -42,6 +42,8 @@ void gnutls_dtls_set_timeouts (gnutls_session_t session, 
unsigned int retrans_ti
   unsigned int total_timeout);
 
 unsigned int gnutls_dtls_get_mtu (gnutls_session_t session);
+unsigned int gnutls_dtls_get_data_mtu (gnutls_session_t session);
+
 void gnutls_dtls_set_mtu (gnutls_session_t session, unsigned int mtu);
 
 typedef struct {
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index cc64d62..dfcf92a 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -1180,7 +1180,7 @@ extern "C"
   typedef ssize_t (*gnutls_push_func) (gnutls_transport_ptr_t, const void *,
                                        size_t);
 
-  typedef int (*gnutls_pull_timeout_func) (gnutls_transport_ptr_t, void*data, 
size_t size, unsigned int ms);
+  typedef int (*gnutls_pull_timeout_func) (gnutls_transport_ptr_t, unsigned 
int ms);
 
   typedef ssize_t (*gnutls_vec_push_func) (gnutls_transport_ptr_t,
                                            const giovec_t * iov, int iovcnt);
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index 021f8db..f5d967e 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -700,6 +700,7 @@ GNUTLS_3_0_0 {
        gnutls_dtls_cookie_verify;
        gnutls_dtls_cookie_send;
        gnutls_dtls_prestate_set;
+       gnutls_dtls_get_data_mtu;
 } GNUTLS_2_12;
 
 GNUTLS_PRIVATE {
diff --git a/lib/system.c b/lib/system.c
index dd2d74f..120fc8b 100644
--- a/lib/system.c
+++ b/lib/system.c
@@ -111,7 +111,7 @@ system_read_peek (gnutls_transport_ptr_t ptr, void *data, 
size_t data_size)
  *
  * Returns -1 on error, 0 on timeout.
  */
-int system_recv_timeout(gnutls_transport_ptr_t ptr, void* data, size_t 
data_size, unsigned int ms)
+int system_recv_timeout(gnutls_transport_ptr_t ptr, unsigned int ms)
 {
 fd_set rfds;
 struct timeval tv;
@@ -128,27 +128,11 @@ int ret, ret2;
     return ret;
 
   
-  if (data_size == 0)
-    {
-      ret2 = recv(GNUTLS_POINTER_TO_INT(ptr), NULL, 0, MSG_PEEK);
-      if (ret2 == -1)
-        return ret2;
+  ret2 = recv(GNUTLS_POINTER_TO_INT(ptr), NULL, 0, MSG_PEEK);
+  if (ret2 == -1)
+    return ret2;
       
-      return ret;
-    }
-
-  /* only report ok if the next message is from the peer we expect
-   * from 
-   */
-  ret = recv(GNUTLS_POINTER_TO_INT(ptr), data, data_size, MSG_PEEK);
-  if (ret > 0)
-    {
-      return ret;
-    }
-  else
-    {
-       return -1;
-    }
+  return ret;
 }
 
 /* Thread stuff */
diff --git a/lib/system.h b/lib/system.h
index bdda73e..b1f5565 100644
--- a/lib/system.h
+++ b/lib/system.h
@@ -8,7 +8,7 @@
 #endif
 
 int system_errno (gnutls_transport_ptr_t);
-int system_recv_timeout(gnutls_transport_ptr_t ptr,void*data, size_t, unsigned 
int ms);
+int system_recv_timeout(gnutls_transport_ptr_t ptr, unsigned int ms);
 
 #ifdef _WIN32
 ssize_t system_write (gnutls_transport_ptr_t ptr, const void *data,
diff --git a/src/cli.c b/src/cli.c
index f9ceda3..7ce2e6e 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -1399,6 +1399,7 @@ socket_open (socket_st * hd, const char *hostname, const 
char *service)
   int sd, err;
   char buffer[MAX_BUF + 1];
   char portname[16] = { 0 };
+  int yes;
 
   printf ("Resolving '%s'...\n", hostname);
   /* get server name */
@@ -1436,6 +1437,16 @@ socket_open (socket_st * hd, const char *hostname, const 
char *service)
       exit (1);
     }
 
+  if (hints.ai_socktype == SOCK_DGRAM)
+    {
+      yes = 1;
+      if (setsockopt (sd, IPPROTO_IP, IP_DF,
+                          (const void *) &yes, sizeof (yes)) < 0)
+        {
+          perror ("setsockopt(IP_DF) failed");
+        }
+    }
+
   hd->secure = 0;
   hd->fd = sd;
   hd->hostname = strdup (hostname);
diff --git a/src/common.h b/src/common.h
index 4a7e1aa..f89592c 100644
--- a/src/common.h
+++ b/src/common.h
@@ -8,6 +8,7 @@
 #include <netdb.h>
 #include <unistd.h>
 #include <netinet/in.h>
+#include <netinet/ip.h>
 #include <signal.h>
 #ifdef _WIN32
 #include <io.h>
diff --git a/src/serv.c b/src/serv.c
index 7b60147..9c868ea 100644
--- a/src/serv.c
+++ b/src/serv.c
@@ -729,7 +729,16 @@ listen_socket (const char *name, int listen_port, int 
socktype)
               continue;
             }
         }
-
+      else
+        {
+          yes = 1;
+          if (setsockopt (s, IPPROTO_IP, IP_DF,
+                          (const void *) &yes, sizeof (yes)) < 0)
+            {
+              perror ("setsockopt(IP_DF) failed");
+            }
+        }
+      
       if (bind (s, ptr->ai_addr, ptr->ai_addrlen) < 0)
         {
           perror ("bind() failed");
diff --git a/src/udp-serv.c b/src/udp-serv.c
index 75cd7e9..3cc3684 100644
--- a/src/udp-serv.c
+++ b/src/udp-serv.c
@@ -15,7 +15,7 @@ typedef struct {
   socklen_t cli_addr_size;
 } priv_data_st;
 
-static int pull_timeout_func(gnutls_transport_ptr_t ptr, void* data, size_t 
data_size, unsigned int ms);
+static int pull_timeout_func(gnutls_transport_ptr_t ptr, unsigned int ms);
 static ssize_t push_func (gnutls_transport_ptr_t p, const void * data, size_t 
size);
 static ssize_t pull_func(gnutls_transport_ptr_t p, void * data, size_t size);
 
@@ -146,7 +146,7 @@ int udp_server(const char* name, int port, int mtu)
 
 /* Wait for data to be received within a timeout period in milliseconds
  */
-static int pull_timeout_func(gnutls_transport_ptr_t ptr, void* data, size_t 
data_size, unsigned int ms)
+static int pull_timeout_func(gnutls_transport_ptr_t ptr, unsigned int ms)
 {
 fd_set rfds;
 struct timeval tv;
@@ -167,17 +167,11 @@ char c;
   if (ret <= 0)
     return ret;
 
-  if (data_size == 0)
-    {
-      data = &c;
-      data_size = 1;
-    }
-
   /* only report ok if the next message is from the peer we expect
    * from 
    */
   cli_addr_size = sizeof(cli_addr);
-  ret = recvfrom(priv->fd, data, data_size, MSG_PEEK, (struct 
sockaddr*)&cli_addr, &cli_addr_size);
+  ret = recvfrom(priv->fd, &c, 1, MSG_PEEK, (struct sockaddr*)&cli_addr, 
&cli_addr_size);
   if (ret > 0)
     {
       if (cli_addr_size == priv->cli_addr_size && memcmp(&cli_addr, 
priv->cli_addr, sizeof(cli_addr))==0)


hooks/post-receive
-- 
GNU gnutls



reply via email to

[Prev in Thread] Current Thread [Next in Thread]