]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Avoided waiting for peer's retransmission to ensure receipt of finished messages...
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Sun, 20 Mar 2011 13:18:57 +0000 (14:18 +0100)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Sun, 20 Mar 2011 13:21:14 +0000 (14:21 +0100)
15 files changed:
lib/gnutls_buffers.c
lib/gnutls_buffers.h
lib/gnutls_dtls.c
lib/gnutls_dtls.h
lib/gnutls_handshake.c
lib/gnutls_handshake.h
lib/gnutls_int.h
lib/gnutls_record.c
lib/includes/gnutls/gnutls.h.in
lib/system.c
lib/system.h
src/cli.c
src/common.h
src/serv.c
src/udp-serv.c

index 31e56b5264cef70c0adc31ba5a39bf05c5afbdf0..778af8d0bc783ad7719b04c7d99c949592e29ee4 100644 (file)
@@ -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 ||
index 60d2e6442a8ad313ab7bd476d97d1526051684e5..bc432bdb7ef06a9936e98a17ab24f2c6fcbbdfc7 100644 (file)
@@ -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)
index 335e237657b85c830cf038662726dfb415d965d5..076be8c643173139d1458c3f78ae7a275f2380ba 100644 (file)
@@ -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 */
index ab4e4da6faffeb6b8c0bc2db6a907ead34390f17..f8436b373128f9773953b06b8889daac861a758b 100644 (file)
 # 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
index 7e0608da3c86d1c5eb1dfce3f2397b08b7d8d12b..fb4c3c2f779245998eb85b996562ca6b766eb3f1 100644 (file)
@@ -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++;
index 6792bbe0cea2aecda9a625ea575b2dc3d2426a10..656c9093b8192d23bbe9469e250ad404d14b9dae 100644 (file)
@@ -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
index 1c188175716af887883fc51596d3f31711f9be58..4884888aa5ed4e5395bba0981c1057bc7cda1808 100644 (file)
@@ -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;
 
 
index cc259c4d0541efbf3e8bc22860a0db1208edb508..19f6aa3d1fe0686458cf7005884e28f588726e0c 100644 (file)
 #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)
index cc64d6290a8f54bf98c8521274c0d0b44a7272cc..dfcf92a12e1a665f4e2c8dfb3207a9ebae19eaf0 100644 (file)
@@ -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);
index dd2d74fc20e889922063861eba0bfb0f305e5e65..120fc8b0ca9507b7995fc0cd104542ed773d4b02 100644 (file)
@@ -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 */
index bdda73e4ca29a1e5d31322869637c98a9a0c6693..b1f556557a25ad945ea5d01e420dc790dfe70eba 100644 (file)
@@ -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,
index f9ceda39d4d69f38dba3797666c2dab877f9264a..7ce2e6edb907e872bcddd0c88117253d7a706485 100644 (file)
--- 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);
index 4a7e1aa6701dd564925a11d5f5bbfc6cf161e4fe..f89592c672de3c68c1fd836de501b3eef333d163 100644 (file)
@@ -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>
index 7b6014775ce34b4e356d5584686882de75c9a7f0..9c868ea81840d5c6c24547660763f130af32bbae 100644 (file)
@@ -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");
index 75cd7e960341a8d03933c214f91a0af42b0ced97..3cc3684ee4f44af530cc338203adbbaafc6c2b5c 100644 (file)
@@ -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)