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-191-g31c0971


From: Nikos Mavrogiannopoulos
Subject: [SCM] GNU gnutls branch, master, updated. gnutls_2_11_6-191-g31c0971
Date: Fri, 18 Feb 2011 01:05:48 +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=31c09710c06478dc6d3892e8a95864cf22d712f2

The branch, master has been updated
       via  31c09710c06478dc6d3892e8a95864cf22d712f2 (commit)
       via  3bad71af582ab6971653ce71fffa16287f9646e5 (commit)
       via  8c72985cdd7b9435bb84b90dff8b8bef604a93e6 (commit)
       via  2ff41a23b8880f658d1407842b34510d24d22b88 (commit)
       via  07f431787d7f198d9e3d7cc14b0e490a3b3cebbf (commit)
       via  6d0bb2339372be2b8f4eabbeaeb34dfc6363cc15 (commit)
       via  239a5ec0faadf13527c487f9db9ad28d8985ee67 (commit)
       via  8fd2d21a51e8ef005869ae286f1a1d9cc3936665 (commit)
       via  d4600185b6fe03fac020a5b5f8e1b825f57a70a8 (commit)
       via  a63df83e829c4b3d73c601a63e1cfdb7a177392b (commit)
       via  df20b0001d43b2f552858b47ef059af61aea6c45 (commit)
       via  af566cf29a1d7e715f1d9f004bbddf412bdc2e67 (commit)
       via  b60f0acfa3c2162201ae79dd789d469ad811d7fc (commit)
       via  3efc6027083def994618f818b42a7febf3530989 (commit)
       via  83231744d53464dfadd7c015097731017d484497 (commit)
       via  dc3070d13a30694847c468829a805f7b35771cc9 (commit)
       via  c83e30404d4c84df703e64302a57ea0f3fc0edd0 (commit)
       via  9146c8b33956ba1f84fb94f3110f5758080d379b (commit)
       via  d36efeead48027dc8ea4f05dac89c1ea65f45d6a (commit)
       via  222f1277bc052ff97dd7b65b431c2c016bd0dfe1 (commit)
       via  3efebded307e49c73ef44483ffb5819ff5c0efd6 (commit)
       via  c6b22639ee42f1cc810fa5a1c367c951986e94f7 (commit)
       via  81291c9df97455bba09fd606afd47bd0299b124c (commit)
       via  9eaa74e2698a4659851de05fcd0f5bcbc5075d96 (commit)
       via  a311c2bc2b1a9c80b00671f4077265b8f1bd5be9 (commit)
       via  929e369c7d63fb5dcfbe12d2316f17ae77d08b84 (commit)
       via  47d20bdbb1c21a42dca612d06687edb3ec56ad64 (commit)
       via  81f08604fb30ebc9762d2e3f152b993ecc40fde4 (commit)
       via  524f8623f2f03ad83e62494d130abb89e8ed6b05 (commit)
       via  9f63e9aec1cd3f4720a02062bfb27bcfc4b097eb (commit)
       via  a439f2cdce782187e3e762ce8e02837602fdb431 (commit)
       via  aceb9810d60e528e9629ec68799f2e1a76cffa02 (commit)
       via  183bc93e31faa4d127ce07c4b86b9428612f49eb (commit)
       via  be09a50d4839d717fc16db2bbd0d91b4ede6a8fb (commit)
       via  f500e3c03137fa1bfdca067ab718cc3df8086a0a (commit)
       via  5c3b44c79c287be6640fb93b3e7c611c43d80c1f (commit)
      from  b9bd3bc58129371e50bfb9eaf920221a82559037 (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 -----------------------------------------------------------------
-----------------------------------------------------------------------

Summary of changes:
 lib/Makefile.am                          |    2 +-
 lib/auth_dhe.c                           |    1 +
 lib/debug.c                              |    3 +
 lib/ext_session_ticket.c                 |    3 +-
 lib/gnutls_algorithms.c                  |   29 +++--
 lib/gnutls_buffers.c                     |  103 ++++++++++++++--
 lib/gnutls_cipher.c                      |   18 ++-
 lib/gnutls_cipher.h                      |    3 +-
 lib/gnutls_constate.c                    |   11 +-
 lib/gnutls_dtls.c                        |  204 ++++++++++++++++++++++++++++++
 lib/{pakchois/dlopen.c => gnutls_dtls.h} |   41 +++----
 lib/gnutls_errors.h                      |    2 +
 lib/gnutls_handshake.c                   |  203 +++++++++++++++++++++++++++---
 lib/gnutls_int.h                         |   88 ++++++++++++-
 lib/gnutls_kx.c                          |    2 +-
 lib/gnutls_mbuffers.h                    |    2 +-
 lib/gnutls_num.c                         |   59 +++++++++
 lib/gnutls_num.h                         |    7 +-
 lib/gnutls_priority.c                    |    1 +
 lib/gnutls_record.c                      |   95 +++++++++++----
 lib/gnutls_state.c                       |   34 +++++
 lib/gnutls_state.h                       |   14 ++
 lib/includes/gnutls/gnutls.h.in          |   15 ++-
 lib/libgnutls.map                        |    1 +
 src/cli-gaa.c                            |  129 +++++++++++---------
 src/cli-gaa.h                            |   48 ++++----
 src/cli.c                                |   10 +-
 src/cli.gaa                              |    7 +-
 28 files changed, 939 insertions(+), 196 deletions(-)
 create mode 100644 lib/gnutls_dtls.c
 copy lib/{pakchois/dlopen.c => gnutls_dtls.h} (51%)

diff --git a/lib/Makefile.am b/lib/Makefile.am
index e96e6de..6a2b1dc 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -81,7 +81,7 @@ COBJECTS = gnutls_record.c gnutls_compress.c debug.c 
gnutls_cipher.c  \
        crypto.c random.c  ext_signature.c cryptodev.c system.c \
        crypto-api.c ext_safe_renegotiation.c gnutls_privkey.c \
        pkcs11.c pkcs11_privkey.c gnutls_pubkey.c pkcs11_write.c locks.c \
-       pkcs11_secret.c hash.c
+       pkcs11_secret.c hash.c gnutls_dtls.c
 
 
 if ENABLE_NETTLE
diff --git a/lib/auth_dhe.c b/lib/auth_dhe.c
index b714e64..fafef62 100644
--- a/lib/auth_dhe.c
+++ b/lib/auth_dhe.c
@@ -253,6 +253,7 @@ proc_dhe_server_kx (gnutls_session_t session, opaque * data,
       sign_algo = _gnutls_tls_aid_to_sign (&aid);
       if (sign_algo == GNUTLS_SIGN_UNKNOWN)
         {
+          _gnutls_x509_log("unknown signature %d.%d\n", aid.sign_algorithm, 
aid.hash_algorithm);
           gnutls_assert ();
           return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
         }
diff --git a/lib/debug.c b/lib/debug.c
index ec4988a..c9b367d 100644
--- a/lib/debug.c
+++ b/lib/debug.c
@@ -81,6 +81,9 @@ _gnutls_handshake2str (gnutls_handshake_description_t 
handshake)
     case GNUTLS_HANDSHAKE_SERVER_HELLO:
       return "SERVER HELLO";
       break;
+    case GNUTLS_HANDSHAKE_HELLO_VERIFY_REQUEST:
+      return "HELLO VERIFY REQUEST";
+      break;
     case GNUTLS_HANDSHAKE_CERTIFICATE_PKT:
       return "CERTIFICATE";
       break;
diff --git a/lib/ext_session_ticket.c b/lib/ext_session_ticket.c
index 25a01a0..9c44b90 100644
--- a/lib/ext_session_ticket.c
+++ b/lib/ext_session_ticket.c
@@ -648,8 +648,7 @@ _gnutls_send_new_session_ticket (gnutls_session_t session, 
int again)
       ticket_len = KEY_NAME_SIZE + IV_SIZE + 2 + ticket.encrypted_state_len
         + MAC_SIZE;
 
-      bufel =
-        _gnutls_handshake_alloc (4 + 2 + ticket_len, 4 + 2 + ticket_len);
+      bufel = _gnutls_handshake_alloc (session, 4 + 2 + ticket_len, 
4+2+ticket_len);
       if (!bufel)
         {
           gnutls_assert ();
diff --git a/lib/gnutls_algorithms.c b/lib/gnutls_algorithms.c
index 7c0bf91..2b2303f 100644
--- a/lib/gnutls_algorithms.c
+++ b/lib/gnutls_algorithms.c
@@ -136,14 +136,16 @@ typedef struct
   gnutls_protocol_t id;         /* gnutls internal version number */
   int major;                    /* defined by the protocol */
   int minor;                    /* defined by the protocol */
+  transport_t transport;       /* Type of transport, stream or datagram */
   int supported;                /* 0 not supported, > 0 is supported */
 } gnutls_version_entry;
 
 static const gnutls_version_entry sup_versions[] = {
-  {"SSL3.0", GNUTLS_SSL3, 3, 0, 1},
-  {"TLS1.0", GNUTLS_TLS1, 3, 1, 1},
-  {"TLS1.1", GNUTLS_TLS1_1, 3, 2, 1},
-  {"TLS1.2", GNUTLS_TLS1_2, 3, 3, 1},
+  {"SSL3.0", GNUTLS_SSL3, 3, 0, GNUTLS_STREAM, 1},
+  {"TLS1.0", GNUTLS_TLS1, 3, 1, GNUTLS_STREAM, 1},
+  {"TLS1.1", GNUTLS_TLS1_1, 3, 2, GNUTLS_STREAM, 1},
+  {"TLS1.2", GNUTLS_TLS1_2, 3, 3, GNUTLS_STREAM, 1},
+  {"DTLS1.0", GNUTLS_DTLS1_0, 254, 255, GNUTLS_DGRAM, 1}, /* 1.1 over datagram 
*/
   {0, 0, 0, 0, 0}
 };
 
@@ -153,6 +155,7 @@ static const gnutls_protocol_t supported_protocols[] = {
   GNUTLS_TLS1,
   GNUTLS_TLS1_1,
   GNUTLS_TLS1_2,
+  GNUTLS_DTLS1_0,
   0
 };
 
@@ -1248,11 +1251,14 @@ gnutls_protocol_t
 _gnutls_version_lowest (gnutls_session_t session)
 {                               /* returns the lowest version supported */
   unsigned int i, min = 0xff;
+  gnutls_protocol_t cur_prot;
 
   for (i = 0; i < session->internals.priorities.protocol.algorithms; i++)
     {
-      if (session->internals.priorities.protocol.priority[i] < min)
-        min = session->internals.priorities.protocol.priority[i];
+      cur_prot = session->internals.priorities.protocol.priority[i];
+
+      if (cur_prot < min && _gnutls_version_is_supported(session, cur_prot))
+       min = cur_prot;
     }
 
   if (min == 0xff)
@@ -1265,11 +1271,14 @@ gnutls_protocol_t
 _gnutls_version_max (gnutls_session_t session)
 {                               /* returns the maximum version supported */
   unsigned int i, max = 0x00;
+  gnutls_protocol_t cur_prot;
 
   for (i = 0; i < session->internals.priorities.protocol.algorithms; i++)
     {
-      if (session->internals.priorities.protocol.priority[i] > max)
-        max = session->internals.priorities.protocol.priority[i];
+      cur_prot = session->internals.priorities.protocol.priority[i];
+
+      if (cur_prot > max && _gnutls_version_is_supported(session, cur_prot))
+       max = cur_prot;
     }
 
   if (max == 0x00)
@@ -1368,7 +1377,8 @@ _gnutls_version_is_supported (gnutls_session_t session,
 {
   int ret = 0;
 
-  GNUTLS_VERSION_ALG_LOOP (ret = p->supported);
+  GNUTLS_VERSION_ALG_LOOP (ret = p->supported && p->transport == 
session->internals.transport);
+
   if (ret == 0)
     return 0;
 
@@ -1403,6 +1413,7 @@ _gnutls_version_has_selectable_sighash (gnutls_protocol_t 
version)
 {
   switch (version)
     {
+    case GNUTLS_DTLS1_0:
     case GNUTLS_TLS1_1:
     case GNUTLS_TLS1_0:
     case GNUTLS_SSL3:
diff --git a/lib/gnutls_buffers.c b/lib/gnutls_buffers.c
index e71476e..692e61b 100644
--- a/lib/gnutls_buffers.c
+++ b/lib/gnutls_buffers.c
@@ -54,6 +54,7 @@
 #include <gnutls_record.h>
 #include <gnutls_buffers.h>
 #include <gnutls_mbuffers.h>
+#include <gnutls_state.h>
 #include <system.h>
 
 #include <errno.h>
@@ -266,14 +267,72 @@ get_errno (gnutls_session_t session)
 }
 
 
-/* This function is like read. But it does not return -1 on error.
- * It does return gnutls_errno instead.
- *
- * Flags are only used if the default recv() function is being used.
- */
 static ssize_t
-_gnutls_read (gnutls_session_t session, mbuffer_st ** bufel,
-              size_t size, gnutls_pull_func pull_func)
+_gnutls_dgram_read (gnutls_session_t session, mbuffer_st **bufel,
+                   gnutls_pull_func pull_func)
+{
+  ssize_t i;
+  char *ptr = alloca (MAX_RECV_SIZE);
+  gnutls_transport_ptr_t fd = session->internals.transport_recv_ptr;
+
+  if (!bufel)
+    {
+      gnutls_assert ();
+      return GNUTLS_E_INTERNAL_ERROR;
+    }
+
+  session->internals.direction = 0;
+
+  reset_errno (session);
+
+  i = pull_func (fd, ptr, MAX_RECV_SIZE);
+
+  if (i < 0)
+    {
+      int err = get_errno (session);
+
+      _gnutls_read_log ("READ: %d returned from %p, errno=%d gerrno=%d\n",
+                       (int) i, fd, errno, session->internals.errnum);
+
+      if (err == EAGAIN)
+       return GNUTLS_E_AGAIN;
+      else if (err == EINTR)
+       return GNUTLS_E_INTERRUPTED;
+      else
+       {
+         gnutls_assert ();
+         return GNUTLS_E_PULL_ERROR;
+       }
+    }
+  else
+    {
+      _gnutls_read_log ("READ: Got %d bytes from %p\n", (int) i, fd);
+      if (i == 0) {
+       /* If we get here, we likely have a stream socket.
+        * FIXME: this probably breaks DCCP. */
+       gnutls_assert ();
+       return GNUTLS_E_INTERNAL_ERROR;
+      }
+
+      *bufel = _mbuffer_alloc (0, i);
+      if (!*bufel)
+       {
+         gnutls_assert ();
+         return GNUTLS_E_MEMORY_ERROR;
+       }
+
+      _mbuffer_append_data (*bufel, ptr, i);
+    }
+
+  if (_gnutls_log_level >= 7)
+    _gnutls_read_log ("READ: read %d bytes from %p\n", (int) i, fd);
+
+  return i;
+}
+
+static ssize_t
+_gnutls_stream_read (gnutls_session_t session, mbuffer_st **bufel,
+                    size_t size, gnutls_pull_func pull_func)
 {
   size_t left;
   ssize_t i = 0;
@@ -357,6 +416,21 @@ finish:
 }
 
 
+/* This function is like read. But it does not return -1 on error.
+ * It does return gnutls_errno instead.
+ *
+ * Flags are only used if the default recv() function is being used.
+ */
+static ssize_t
+_gnutls_read (gnutls_session_t session, mbuffer_st **bufel,
+             size_t size, gnutls_pull_func pull_func)
+{
+  if (_gnutls_is_dtls (session))
+    /* Size is not passed, since a whole datagram will be read. */
+    return _gnutls_dgram_read (session, bufel, pull_func);
+  else
+    return _gnutls_stream_read (session, bufel, size, pull_func);
+}
 
 static ssize_t
 _gnutls_writev_emu (gnutls_session_t session, const giovec_t * giovec,
@@ -518,6 +592,14 @@ _gnutls_io_read_buffered (gnutls_session_t session, size_t 
total,
         }
     }
 
+  if(_gnutls_is_dtls(session)
+     && session->internals.record_recv_buffer.byte_length != 0)
+    {
+      /* Attempt to read across records while using DTLS. */
+      gnutls_assert();
+      return GNUTLS_E_INVALID_REQUEST;
+    }
+
   /* min is over zero. recvdata is the data we must
    * receive in order to return the requested data.
    */
@@ -578,7 +660,7 @@ _gnutls_io_read_buffered (gnutls_session_t session, size_t 
total,
    * select think, that the socket is ready for reading.
    * MSG_PEEK is only used with berkeley style sockets.
    */
-  if (ret == readsize && recvlowat > 0)
+  if (ret == readsize && recvlowat > 0 && !_gnutls_is_dtls(session))
     {
       ret2 = _gnutls_read (session, &bufel, recvlowat, system_read_peek);
 
@@ -624,7 +706,10 @@ _gnutls_io_read_buffered (gnutls_session_t session, size_t 
total,
       return 0;
     }
 
-  ret = session->internals.record_recv_buffer.byte_length;
+  if(_gnutls_is_dtls(session))
+    ret = MIN(total, session->internals.record_recv_buffer.byte_length);
+  else
+    ret = session->internals.record_recv_buffer.byte_length;
 
   if ((ret > 0) && ((size_t) ret < total))
     {
diff --git a/lib/gnutls_cipher.c b/lib/gnutls_cipher.c
index f238fd4..eeee430 100644
--- a/lib/gnutls_cipher.c
+++ b/lib/gnutls_cipher.c
@@ -40,6 +40,7 @@
 #include "gnutls_kx.h"
 #include "gnutls_record.h"
 #include "gnutls_constate.h"
+#include <gnutls_state.h>
 #include <random.h>
 
 static int _gnutls_compressed2ciphertext (gnutls_session_t session,
@@ -51,7 +52,7 @@ static int _gnutls_ciphertext2compressed (gnutls_session_t 
session,
                                    opaque * compress_data,
                                    int compress_size,
                                    gnutls_datum_t ciphertext, uint8_t type,
-                                   record_parameters_st * params);
+                                   record_parameters_st * params, uint64* 
sequence);
 
 inline static int
 is_write_comp_null (record_parameters_st * record_params)
@@ -125,7 +126,11 @@ _gnutls_encrypt (gnutls_session_t session, const opaque * 
headers,
 
   /* copy the headers */
   memcpy (ciphertext, headers, headers_size);
-  _gnutls_write_uint16 (ret, &ciphertext[3]);
+  
+  if(_gnutls_is_dtls(session))
+    _gnutls_write_uint16 (ret, &ciphertext[11]);
+  else
+    _gnutls_write_uint16 (ret, &ciphertext[3]);
 
   return ret + headers_size;
 }
@@ -137,7 +142,7 @@ int
 _gnutls_decrypt (gnutls_session_t session, opaque * ciphertext,
                  size_t ciphertext_size, uint8_t * data,
                  size_t max_data_size, content_type_t type,
-                 record_parameters_st * params)
+                 record_parameters_st * params, uint64 *sequence)
 {
   gnutls_datum_t gtxt;
   gnutls_datum_t gcipher;
@@ -156,7 +161,7 @@ _gnutls_decrypt (gnutls_session_t session, opaque * 
ciphertext,
 
   ret =
     _gnutls_ciphertext2compressed (session, data, max_data_size,
-                                   gcipher, type, params);
+                                   gcipher, type, params, sequence);
   if (ret < 0)
     {
       return ret;
@@ -434,7 +439,7 @@ _gnutls_ciphertext2compressed (gnutls_session_t session,
                                opaque * compress_data,
                                int compress_size,
                                gnutls_datum_t ciphertext, uint8_t type,
-                               record_parameters_st * params)
+                               record_parameters_st * params, uint64* sequence)
 {
   uint8_t tag[MAX_HASH_SIZE];
   uint8_t pad;
@@ -492,8 +497,7 @@ _gnutls_ciphertext2compressed (gnutls_session_t session,
        * MAC.
        */
       preamble_size =
-        make_preamble (UINT64DATA
-                       (params->read.sequence_number), type,
+        make_preamble (UINT64DATA(*sequence), type,
                        length, ver, preamble);
 
       _gnutls_auth_cipher_add_auth (&params->read.cipher_state, preamble, 
preamble_size);
diff --git a/lib/gnutls_cipher.h b/lib/gnutls_cipher.h
index 5a47f20..19667de 100644
--- a/lib/gnutls_cipher.h
+++ b/lib/gnutls_cipher.h
@@ -31,4 +31,5 @@ int _gnutls_encrypt (gnutls_session_t session, const opaque * 
headers,
 
 int _gnutls_decrypt (gnutls_session_t session, opaque * ciphertext,
                      size_t ciphertext_size, uint8_t * data, size_t data_size,
-                     content_type_t type, record_parameters_st * params);
+                     content_type_t type, record_parameters_st * params,
+                     uint64* sequence);
diff --git a/lib/gnutls_constate.c b/lib/gnutls_constate.c
index 0546e92..aadb110 100644
--- a/lib/gnutls_constate.c
+++ b/lib/gnutls_constate.c
@@ -291,7 +291,7 @@ _gnutls_set_keys (gnutls_session_t session, 
record_parameters_st * params,
 }
 
 static int
-_gnutls_init_record_state (record_parameters_st * params, int ver, int read,
+_gnutls_init_record_state (record_parameters_st * params, int ver, int d,
                            record_state_st * state)
 {
   int ret;
@@ -309,7 +309,7 @@ _gnutls_init_record_state (record_parameters_st * params, 
int ver, int read,
     return gnutls_assert_val (ret);
 
   state->compression_state =
-    _gnutls_comp_init (params->compression_algorithm, read);
+    _gnutls_comp_init (params->compression_algorithm, d);
 
   if (state->compression_state == GNUTLS_COMP_FAILED)
     return gnutls_assert_val (GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM);
@@ -731,6 +731,9 @@ _gnutls_epoch_alloc (gnutls_session_t session, uint16_t 
epoch,
   (*slot)->mac_algorithm = GNUTLS_MAC_UNKNOWN;
   (*slot)->compression_algorithm = GNUTLS_COMP_UNKNOWN;
 
+  if (_gnutls_is_dtls (session))
+    _gnutls_write_uint16 (epoch, UINT64DATA((*slot)->write.sequence_number));
+
   if (out != NULL)
     *out = *slot;
 
@@ -783,7 +786,7 @@ _gnutls_epoch_gc (gnutls_session_t session)
 }
 
 static inline void
-free_record_state (record_state_st * state, int read)
+free_record_state (record_state_st * state, int d)
 {
   _gnutls_free_datum (&state->mac_secret);
   _gnutls_free_datum (&state->IV);
@@ -792,7 +795,7 @@ free_record_state (record_state_st * state, int read)
   _gnutls_auth_cipher_deinit (&state->cipher_state);
 
   if (state->compression_state != NULL)
-    _gnutls_comp_deinit (state->compression_state, read);
+    _gnutls_comp_deinit (state->compression_state, d);
 }
 
 void
diff --git a/lib/gnutls_dtls.c b/lib/gnutls_dtls.c
new file mode 100644
index 0000000..d0934a5
--- /dev/null
+++ b/lib/gnutls_dtls.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2009 Free Software Foundation (copyright assignement pending)
+ *
+ * Author: Jonathan Bastien-Filiatrault
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* Functions that relate to DTLS retransmission and reassembly.
+ */
+
+#include "gnutls_int.h"
+#include "gnutls_errors.h"
+#include "debug.h"
+#include "gnutls_dtls.h"
+#include "gnutls_record.h"
+
+/* This function is called once a handshake message is ready to be
+ * queued in the next outgoing flight. The actual transmission occurs
+ * in _gnutls_dtls_transmit.
+ *
+ * This function is called from the handshake layer.
+ */
+int
+_gnutls_dtls_handshake_enqueue (gnutls_session_t session,
+                               opaque *data,
+                               uint32_t datasize,
+                               gnutls_handshake_description_t type,
+                               uint16_t sequence)
+{
+  dtls_hsk_retransmit_buffer *msg;
+
+  msg = gnutls_malloc (sizeof(dtls_hsk_retransmit_buffer));
+  if (msg == NULL)
+    {
+      gnutls_assert ();
+      return GNUTLS_E_MEMORY_ERROR;
+    }
+
+  msg->msg.size = datasize - DTLS_HANDSHAKE_HEADER_SIZE;
+
+  msg->msg.data = gnutls_malloc (msg->msg.size);
+  if (msg->msg.data == NULL)
+    {
+      gnutls_free (msg);
+      gnutls_assert ();
+      return GNUTLS_E_MEMORY_ERROR;
+    }
+
+  memcpy (msg->msg.data, data + DTLS_HANDSHAKE_HEADER_SIZE, msg->msg.size);
+
+  msg->next = NULL;
+  /* FIXME: dummy epoch */
+  msg->epoch = 0;
+  msg->type = type;
+  msg->sequence = sequence;
+
+  _gnutls_dtls_log ("DTLS[%p]: Enqueued Packet[%u] %s(%d) with length: %u\n",
+                   session, (uint)sequence, _gnutls_handshake2str (type),
+                   type, msg->msg.size);
+
+  *(session->internals.dtls.retransmit_end) = msg;
+  session->internals.dtls.retransmit_end = &msg->next;
+
+  return 0;
+}
+
+/* This function fragments and transmits a previously buffered
+ * outgoing message. */
+static inline int
+transmit_message (gnutls_session_t session,
+                 dtls_hsk_retransmit_buffer *msg)
+{
+  opaque *data;
+  uint offset, frag_len;
+  const uint mtu = session->internals.dtls.hsk_mtu;
+
+  data = gnutls_malloc (DTLS_HANDSHAKE_HEADER_SIZE + mtu);
+  if (data == NULL)
+    {
+      gnutls_assert ();
+      return GNUTLS_E_MEMORY_ERROR;
+    }
+
+  /* Write fixed headers
+   */
+
+  /* Handshake type */
+  data[0] = (uint8_t) msg->type;
+
+  /* Total length */
+  _gnutls_write_uint24 (msg->msg.size, &data[1]);
+
+  /* Handshake sequence */
+  _gnutls_write_uint16 (msg->sequence, &data[4]);
+
+  /* Chop up and send handshake message into mtu-size pieces. */
+  for (offset=0; offset < msg->msg.size; offset += mtu)
+    {
+      /* Calculate fragment length */
+      if(offset + mtu > msg->msg.size)
+       frag_len = msg->msg.size - offset;
+      else
+       frag_len = mtu;
+
+      /* Fragment offset */
+      _gnutls_write_uint24 (offset, &data[6]);
+
+      /* Fragment length */
+      _gnutls_write_uint24 (frag_len, &data[9]);
+
+      memcpy (&data[12], msg->msg.data + offset, frag_len);
+
+      _gnutls_dtls_log ("DTLS[%p]: Sending Packet[%u] fragment %s(%d) with "
+                       "length: %u, offset: %u, fragment length: %u\n",
+                       session, msg->sequence,
+                       _gnutls_handshake2str (msg->type),
+                       msg->type, msg->msg.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. */
+      _gnutls_send_int (session, GNUTLS_HANDSHAKE, msg->type, 
EPOCH_WRITE_CURRENT,
+                       data, DTLS_HANDSHAKE_HEADER_SIZE + frag_len, 0);
+   }
+
+  gnutls_free (data);
+  return 0;
+}
+
+/* This function transmits the flight that has been previously
+ * buffered.
+ *
+ * This function is called from the handshake layer and calls the
+ * record layer.
+ */
+int
+_gnutls_dtls_transmit (gnutls_session_t session)
+{
+  /* PREPARING -> SENDING state transition */
+  dtls_hsk_retransmit_buffer *msg;
+
+  _gnutls_dtls_log ("DTLS[%p]: Start of flight transmission.\n", session);
+
+  for (msg = session->internals.dtls.retransmit; msg != NULL; msg = msg->next)
+    transmit_message (session, msg);
+  _gnutls_io_write_flush (session);
+
+
+  _gnutls_dtls_log ("DTLS[%p]: End of flight transmission.\n", session);
+
+  _gnutls_dtls_clear_outgoing_buffer (session);
+
+  /* SENDING -> WAITING state transition */
+  return 0;
+}
+
+/* This function clears the outgoing flight buffer. */
+void
+_gnutls_dtls_clear_outgoing_buffer (gnutls_session_t session)
+{
+  dtls_hsk_retransmit_buffer *msg, *next;
+
+  _gnutls_dtls_log ("DTLS[%p]: Clearing outgoing buffer.\n", session);
+
+  for (msg = session->internals.dtls.retransmit; msg != NULL;)
+    {
+      next = msg->next;
+
+      gnutls_free (msg->msg.data);
+      gnutls_free (msg);
+
+      msg = next;
+    }
+
+  session->internals.dtls.retransmit_end = &session->internals.dtls.retransmit;
+  session->internals.dtls.retransmit = NULL;
+}
+
+void
+_gnutls_dtls_split_sequence (const uint64 *input,
+                            uint16_t *epoch, uint64_t *sequence)
+{
+  *epoch = _gnutls_read_uint16 (UINT64DATA(*input));
+  *sequence = _gnutls_read_uint48 (&UINT64DATA(*input)[2]);
+
+  fprintf(stderr, "%04x:%012lx\n", *epoch, *sequence);
+}
diff --git a/lib/pakchois/dlopen.c b/lib/gnutls_dtls.h
similarity index 51%
copy from lib/pakchois/dlopen.c
copy to lib/gnutls_dtls.h
index 624f302..f870c1b 100644
--- a/lib/pakchois/dlopen.c
+++ b/lib/gnutls_dtls.h
@@ -1,12 +1,11 @@
 /*
- * Copyright (C) 2010
- * Free Software Foundation, Inc.
+ * Copyright (C) 2009 Free Software Foundation (copyright assignement pending)
  *
- * Author: Nikos Mavrogiannopoulos
+ * Author: Jonathan Bastien-Filiatrault
  *
- * This file is part of GnuTLS.
+ * This file is part of GNUTLS.
  *
- * The GnuTLS is free software; you can redistribute it and/or
+ * The GNUTLS library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
  * as published by the Free Software Foundation; either version 2.1 of
  * the License, or (at your option) any later version.
@@ -23,29 +22,19 @@
  *
  */
 
-#include "dlopen.h"
+#ifndef DTLS_H
+# define DTLS_H
 
-#ifdef _WIN32
+#include "gnutls_int.h"
 
-#include <windows.h>
+int _gnutls_dtls_handshake_enqueue(gnutls_session_t session,
+                                  opaque *data,
+                                  uint32_t datasize,
+                                  gnutls_handshake_description_t type,
+                                  uint16_t sequence);
 
-void *
-dlopen (const char *filename, int flag)
-{
-  return LoadLibrary (filename);
-}
-
-
-void *
-dlsym (void *handle, const char *symbol)
-{
-  return GetProcAddress ((HINSTANCE) handle, symbol);
-}
-
-int
-dlclose (void *handle)
-{
-  FreeLibrary ((HINSTANCE) handle);
-}
+int _gnutls_dtls_transmit(gnutls_session_t session);
+void _gnutls_dtls_clear_outgoing_buffer(gnutls_session_t session);
+void _gnutls_dtls_split_sequence(const uint64 *input, uint16_t *epoch, 
uint64_t *sequence);
 
 #endif
diff --git a/lib/gnutls_errors.h b/lib/gnutls_errors.h
index 095a084..5444042 100644
--- a/lib/gnutls_errors.h
+++ b/lib/gnutls_errors.h
@@ -65,6 +65,7 @@ _gnutls_log (int, const char *fmt, ...)
 #define _gnutls_buffers_log(...) LEVEL_EQ(6, __VA_ARGS__)
 #define _gnutls_hard_log(...) LEVEL(9, __VA_ARGS__)
 #define _gnutls_record_log(...) LEVEL(4, __VA_ARGS__)
+# define _gnutls_dtls_log(...) LEVEL(6, __VA_ARGS__)
 #define _gnutls_read_log(...) LEVEL_EQ(7, __VA_ARGS__)
 #define _gnutls_write_log(...) LEVEL_EQ(7, __VA_ARGS__)
 #define _gnutls_x509_log(...) LEVEL(1, __VA_ARGS__)
@@ -75,6 +76,7 @@ _gnutls_log (int, const char *fmt, ...)
 #define _gnutls_buffers_log _gnutls_null_log
 #define _gnutls_hard_log _gnutls_null_log
 #define _gnutls_record_log _gnutls_null_log
+# define _gnutls_dtls_log _gnutls_null_log
 #define _gnutls_read_log _gnutls_null_log
 #define _gnutls_write_log _gnutls_null_log
 #define _gnutls_x509_log _gnutls_null_log
diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c
index 84fb9e1..81bb263 100644
--- a/lib/gnutls_handshake.c
+++ b/lib/gnutls_handshake.c
@@ -33,6 +33,7 @@
 #include "gnutls_algorithms.h"
 #include "gnutls_compress.h"
 #include "gnutls_cipher.h"
+#include "gnutls_dtls.h"
 #include "gnutls_buffers.h"
 #include "gnutls_mbuffers.h"
 #include "gnutls_kx.h"
@@ -75,6 +76,9 @@ _gnutls_handshake_hash_add_recvd (gnutls_session_t session,
                                   opaque * header, uint16_t header_size,
                                   opaque * dataptr, uint32_t datalen);
 
+static int
+_gnutls_recv_hello_verify_request (gnutls_session_t session,
+                                  opaque * data, int datalen);
 
 
 /* Clears the handshake hash buffers and handles.
@@ -672,8 +676,7 @@ _gnutls_send_finished (gnutls_session_t session, int again)
 
   if (again == 0)
     {
-      bufel =
-        _gnutls_handshake_alloc (MAX_VERIFY_DATA_SIZE, MAX_VERIFY_DATA_SIZE);
+      bufel = _gnutls_handshake_alloc (session, MAX_VERIFY_DATA_SIZE, 
MAX_VERIFY_DATA_SIZE);
       if (bufel == NULL)
         {
           gnutls_assert ();
@@ -1093,7 +1096,7 @@ _gnutls_send_empty_handshake (gnutls_session_t session,
 
   if (again == 0)
     {
-      bufel = _gnutls_handshake_alloc (0, 0);
+      bufel = _gnutls_handshake_alloc (session, 0, 0);
       if (bufel == NULL)
         {
           gnutls_assert ();
@@ -1170,7 +1173,7 @@ _gnutls_send_handshake (gnutls_session_t session, 
mbuffer_st * bufel,
 {
   int ret;
   uint8_t *data;
-  uint32_t datasize;
+  uint32_t datasize, i_datasize;
   int pos = 0;
 
   if (bufel == NULL)
@@ -1185,18 +1188,52 @@ _gnutls_send_handshake (gnutls_session_t session, 
mbuffer_st * bufel,
 
   /* first run */
   data = _mbuffer_get_uhead_ptr (bufel);
-  datasize =
-    _mbuffer_get_udata_size (bufel) + _mbuffer_get_uhead_size (bufel);
+  i_datasize = _mbuffer_get_udata_size(bufel);
+  datasize = i_datasize + _mbuffer_get_uhead_size (bufel);
 
   data[pos++] = (uint8_t) type;
   _gnutls_write_uint24 (_mbuffer_get_udata_size (bufel), &data[pos]);
   pos += 3;
 
+  /* Add DTLS handshake fragment headers.  The message will be
+   * fragmented later by the fragmentation sub-layer. All fields must
+   * be set properly for HMAC. The HMAC requires we pretend that the
+   * message was sent in a single fragment. */
+  if (_gnutls_is_dtls(session))
+    {
+      _gnutls_write_uint16 (session->internals.dtls.hsk_write_seq++, 
&data[pos]);
+      pos += 2;
+
+      /* Fragment offset */
+      _gnutls_write_uint24 (0, &data[pos]);
+      pos += 3;
+
+      /* Fragment length */
+      _gnutls_write_uint24 (i_datasize, &data[pos]);
+      pos += 3;
+    }
+
   _gnutls_handshake_log ("HSK[%p]: %s was sent [%ld bytes]\n",
                          session, _gnutls_handshake2str (type),
                          (long) datasize);
 
 
+  /* If we send a second or more ClientHello due to a
+     HelloVerifyRequest, we only remember the last ClientHello
+     sent for hashing purposes. */
+  if (_gnutls_is_dtls(session)
+      && type == GNUTLS_HANDSHAKE_CLIENT_HELLO
+      && (session->internals.last_handshake_out == 
GNUTLS_HANDSHAKE_CLIENT_HELLO
+         || session->internals.last_handshake_out == -1))
+    {
+      _gnutls_handshake_hash_buffers_clear (session);
+      if ((ret = _gnutls_handshake_hash_init (session)) < 0)
+       {
+         gnutls_assert ();
+         return ret;
+       }
+    }
+
   /* Here we keep the handshake messages in order to hash them...
    */
   if (type != GNUTLS_HANDSHAKE_HELLO_REQUEST)
@@ -1210,7 +1247,11 @@ _gnutls_send_handshake (gnutls_session_t session, 
mbuffer_st * bufel,
 
   session->internals.last_handshake_out = type;
 
-  _gnutls_handshake_io_cache_int (session, type, bufel);
+  if (_gnutls_is_dtls(session))
+    _gnutls_dtls_handshake_enqueue (session, data, datasize, type,
+                                   session->internals.dtls.hsk_write_seq-1);
+  else
+    _gnutls_handshake_io_cache_int (session, type, bufel);
 
   switch (type)
     {
@@ -1370,7 +1411,11 @@ _gnutls_recv_handshake_header (gnutls_session_t session,
   session->internals.handshake_header_buffer.packet_length = length32;
   session->internals.handshake_header_buffer.recv_type = *recv_type;
 
-  if (*recv_type != type)
+  if (_gnutls_is_dtls (session)
+      && type == GNUTLS_HANDSHAKE_SERVER_HELLO
+      && *recv_type == GNUTLS_HANDSHAKE_HELLO_VERIFY_REQUEST)
+    return length32;
+  else if (*recv_type != type)
     {
       gnutls_assert ();
       return GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET;
@@ -1549,6 +1594,18 @@ _gnutls_recv_handshake (gnutls_session_t session, 
uint8_t ** data,
         }
 
       break;
+    case GNUTLS_HANDSHAKE_HELLO_VERIFY_REQUEST:
+      ret = _gnutls_recv_hello_verify_request (session, dataptr, length32);
+      gnutls_free (dataptr);
+
+      if (ret < 0)
+       break;
+      else
+       /* Signal our caller we have received a verification cookie
+          and ClientHello needs to be sent again. */
+       ret = 1;
+
+      break;
     case GNUTLS_HANDSHAKE_SERVER_HELLO_DONE:
       if (length32 == 0)
         ret = 0;
@@ -2034,6 +2091,7 @@ _gnutls_send_client_hello (gnutls_session_t session, int 
again)
   int rehandshake = 0;
   uint8_t session_id_len =
     session->internals.resumed_security_parameters.session_id_size;
+  uint8_t cookie_len;
 
   _gnutls_buffer_init(&extdata);
 
@@ -2044,13 +2102,20 @@ _gnutls_send_client_hello (gnutls_session_t session, 
int again)
 
   if (again == 0)
     {
+      if(_gnutls_is_dtls(session))
+       {
+         cookie_len = session->internals.dtls.cookie_len + 1;
+       }
+      else
+       {
+         cookie_len = 0;
+       }
 
-      datalen = 2 + (session_id_len + 1) + GNUTLS_RANDOM_SIZE;
+      datalen = 2 + (session_id_len + 1) + GNUTLS_RANDOM_SIZE + cookie_len;
       /* 2 for version, (4 for unix time + 28 for random 
bytes==GNUTLS_RANDOM_SIZE) 
        */
 
-      bufel =
-        _gnutls_handshake_alloc (datalen, datalen + MAX_EXT_DATA_LENGTH);
+      bufel = _gnutls_handshake_alloc (session, datalen, 
datalen+MAX_EXT_DATA_LENGTH);
       if (bufel == NULL)
         {
           gnutls_assert ();
@@ -2107,10 +2172,17 @@ _gnutls_send_client_hello (gnutls_session_t session, 
int again)
 
       /* Generate random data 
        */
-      _gnutls_tls_create_random (rnd);
-      _gnutls_set_client_random (session, rnd);
+      if (!_gnutls_is_dtls (session)
+         || session->internals.dtls.hsk_hello_verify_requests == 0)
+       {
+         _gnutls_tls_create_random (rnd);
+         _gnutls_set_client_random (session, rnd);
+
+         memcpy (&data[pos], rnd, GNUTLS_RANDOM_SIZE);
+       }
+      else
+       memcpy (&data[pos], session->security_parameters.client_random, 
GNUTLS_RANDOM_SIZE);
 
-      memcpy (&data[pos], rnd, GNUTLS_RANDOM_SIZE);
       pos += GNUTLS_RANDOM_SIZE;
 
       /* Copy the Session ID 
@@ -2125,6 +2197,14 @@ _gnutls_send_client_hello (gnutls_session_t session, int 
again)
           pos += session_id_len;
         }
 
+      /* Copy the DTLS cookie
+       */
+      if (_gnutls_is_dtls(session))
+       {
+         data[pos++] = session->internals.dtls.cookie_len;
+         memcpy(&data[pos], &session->internals.dtls.cookie, 
session->internals.dtls.cookie_len);
+         pos += session->internals.dtls.cookie_len;
+       }
 
       /* Copy the ciphersuites.
        *
@@ -2224,8 +2304,7 @@ _gnutls_send_server_hello (gnutls_session_t session, int 
again)
           goto fail;
         }
 
-      bufel =
-        _gnutls_handshake_alloc (datalen + extdata.length, datalen + 
extdata.length);
+      bufel = _gnutls_handshake_alloc (session, datalen + extdata.length, 
datalen + extdata.length);
       if (bufel == NULL)
         {
           gnutls_assert ();
@@ -2338,6 +2417,61 @@ _gnutls_recv_hello (gnutls_session_t session, opaque * 
data, int datalen)
   return 0;
 }
 
+static int
+_gnutls_recv_hello_verify_request (gnutls_session_t session,
+                                  opaque * data, int datalen)
+{
+  ssize_t len = datalen;
+  size_t pos = 0;
+  uint8_t cookie_len;
+  unsigned int nb_verifs;
+
+  if (!_gnutls_is_dtls (session)
+      || session->security_parameters.entity == GNUTLS_SERVER)
+    {
+      gnutls_assert ();
+      return GNUTLS_E_UNEXPECTED_PACKET;
+    }
+
+  nb_verifs = ++session->internals.dtls.hsk_hello_verify_requests;
+  if (nb_verifs >= MAX_HANDSHAKE_HELLO_VERIFY_REQUESTS)
+    {
+      /* The server is either buggy, malicious or changing cookie
+        secrets _way_ too fast. */
+      gnutls_assert ();
+      return GNUTLS_E_UNEXPECTED_PACKET;
+    }
+
+  /* TODO: determine if we need to do anything with the server version field */
+  DECR_LEN (len, 2);
+  pos += 2;
+
+  DECR_LEN (len, 1);
+  cookie_len = data[pos];
+  pos++;
+
+  if (cookie_len > DTLS_MAX_COOKIE_SIZE)
+    {
+      gnutls_assert ();
+      return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
+    }
+
+  DECR_LEN (len, cookie_len);
+
+  session->internals.dtls.cookie_len = cookie_len;
+  memcpy (session->internals.dtls.cookie, &data[pos], cookie_len);
+
+  pos += cookie_len;
+
+  if (len != 0)
+    {
+      gnutls_assert ();
+      return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
+    }
+
+  return 0;
+}
+
 /* The packets in gnutls_handshake (it's more broad than original TLS 
handshake)
  *
  *     Client                                               Server
@@ -2541,7 +2675,7 @@ _gnutls_send_supplemental (gnutls_session_t session, int 
again)
           return ret;
         }
 
-      bufel = _gnutls_handshake_alloc (buf.length, buf.length);
+      bufel = _gnutls_handshake_alloc(session, buf.length, buf.length);
       if (bufel == NULL)
         {
           gnutls_assert ();
@@ -2639,7 +2773,10 @@ gnutls_handshake (gnutls_session_t session)
 
   if (session->security_parameters.entity == GNUTLS_CLIENT)
     {
-      ret = _gnutls_handshake_client (session);
+      do
+       {
+         ret = _gnutls_handshake_client (session);
+       } while (ret == 1);
     }
   else
     {
@@ -2721,6 +2858,24 @@ _gnutls_handshake_client (gnutls_session_t session)
       STATE = STATE1;
       IMED_RET ("send hello", ret, 1);
 
+      _gnutls_dtls_transmit(session);
+
+    case STATE11:
+      if (_gnutls_is_dtls (session))
+       {
+         ret =
+           _gnutls_recv_handshake (session, NULL, NULL,
+                                   GNUTLS_HANDSHAKE_HELLO_VERIFY_REQUEST,
+                                   OPTIONAL_PACKET);
+         STATE = STATE11;
+         IMED_RET ("recv hello verify", ret, 1);
+
+         if (ret == 1)
+           {
+             STATE = STATE0;
+             return 1;
+           }
+       }
     case STATE2:
       /* receive the server hello */
       ret =
@@ -2800,6 +2955,7 @@ _gnutls_handshake_client (gnutls_session_t session)
           _gnutls_send_client_certificate_verify (session, AGAIN (STATE9));
       STATE = STATE9;
       IMED_RET ("send client certificate verify", ret, 1);
+      _gnutls_dtls_transmit(session);
 
       STATE = STATE0;
     default:
@@ -2873,6 +3029,7 @@ _gnutls_send_handshake_final (gnutls_session_t session, 
int init)
           return ret;
         }
 
+      _gnutls_dtls_transmit(session);
       STATE = STATE0;
     default:
       break;
@@ -3291,6 +3448,7 @@ _gnutls_remove_unwanted_ciphersuites (gnutls_session_t 
session,
   int newSuiteSize = 0, i;
   gnutls_certificate_credentials_t cert_cred;
   gnutls_kx_algorithm_t kx;
+  gnutls_cipher_algorithm_t cid;
   int server = session->security_parameters.entity == GNUTLS_SERVER ? 1 : 0;
   gnutls_kx_algorithm_t *alg = NULL;
   int alg_size = 0;
@@ -3375,6 +3533,15 @@ _gnutls_remove_unwanted_ciphersuites (gnutls_session_t 
session,
             delete = 1;
         }
 
+      /* if dtls and not appropriate for dtls */
+      if(_gnutls_is_dtls(session))
+       {
+         cid = _gnutls_cipher_suite_get_cipher_algo (&(*cipherSuites)[i]);
+
+         if(cid == GNUTLS_CIPHER_ARCFOUR_128 || cid == 
GNUTLS_CIPHER_ARCFOUR_40)
+           delete = 1;
+       }
+
       memcpy (&cs.suite, &(*cipherSuites)[i].suite, 2);
 
       if (delete == 0)
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index ed35489..90efdb5 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -57,6 +57,11 @@ typedef struct
   unsigned char i[8];
 } uint64;
 
+typedef struct
+{
+  unsigned char i[6];
+} uint48;
+
 #include <gnutls/gnutls.h>
 
 /*
@@ -139,9 +144,21 @@ typedef struct
 /* expire time for resuming sessions */
 #define DEFAULT_EXPIRE_TIME 3600
 
+typedef enum transport_t
+{
+  GNUTLS_STREAM,
+  GNUTLS_DGRAM
+} transport_t;
+
 /* the maximum size of encrypted packets */
+#define IS_DTLS (session->internals.transport == GNUTLS_DGRAM)
+
 #define DEFAULT_MAX_RECORD_SIZE 16384
-#define RECORD_HEADER_SIZE 5
+#define TLS_RECORD_HEADER_SIZE 5
+#define DTLS_RECORD_HEADER_SIZE (TLS_RECORD_HEADER_SIZE+8)
+#define RECORD_HEADER_SIZE (IS_DTLS ? DTLS_RECORD_HEADER_SIZE : 
TLS_RECORD_HEADER_SIZE)
+#define MAX_RECORD_HEADER_SIZE DTLS_RECORD_HEADER_SIZE
+
 #define MAX_RECORD_SEND_SIZE 
(size_t)session->security_parameters.max_record_send_size
 #define MAX_RECORD_RECV_SIZE 
(size_t)session->security_parameters.max_record_recv_size
 #define MAX_PAD_SIZE 255
@@ -149,7 +166,21 @@ typedef struct
 #define MAX_RECORD_OVERHEAD 
(MAX_CIPHER_BLOCK_SIZE/*iv*/+MAX_PAD_SIZE+EXTRA_COMP_SIZE)
 #define MAX_RECV_SIZE 
(MAX_RECORD_OVERHEAD+MAX_RECORD_RECV_SIZE+RECORD_HEADER_SIZE)
 
-#define HANDSHAKE_HEADER_SIZE 4
+#define TLS_HANDSHAKE_HEADER_SIZE 4
+#define DTLS_HANDSHAKE_HEADER_SIZE (TLS_HANDSHAKE_HEADER_SIZE+8)
+#define HANDSHAKE_HEADER_SIZE (IS_DTLS ? DTLS_HANDSHAKE_HEADER_SIZE : 
TLS_HANDSHAKE_HEADER_SIZE)
+#define MAX_HANDSHAKE_HEADER_SIZE DTLS_HANDSHAKE_HEADER_SIZE
+
+/* This is the maximum handshake message size we send without
+   fragmentation. This currently ignores record layer overhead. */
+#define DTLS_DEFAULT_MTU 1200
+
+/* the maximum size of the DTLS cookie */
+#define DTLS_MAX_COOKIE_SIZE 32
+
+/* The maximum number of HELLO_VERIFY_REQUEST messages the client
+   processes before aborting. */
+#define MAX_HANDSHAKE_HELLO_VERIFY_REQUESTS 5
 
 /* defaults for verification functions
  */
@@ -184,7 +215,8 @@ typedef enum change_cipher_spec_t
 typedef enum handshake_state_t
 { STATE0 = 0, STATE1, STATE2,
   STATE3, STATE4, STATE5,
-  STATE6, STATE7, STATE8, STATE9, STATE20 = 20, STATE21, STATE22,
+  STATE6, STATE7, STATE8, STATE9, STATE11 = 11,
+  STATE20 = 20, STATE21, STATE22,
   STATE30 = 30, STATE31, STATE40 = 40, STATE41, STATE50 = 50,
   STATE60 = 60, STATE61, STATE62, STATE70, STATE71
 } handshake_state_t;
@@ -224,6 +256,7 @@ typedef enum content_type_t
   GNUTLS_INNER_APPLICATION = 24
 } content_type_t;
 
+
 #define GNUTLS_PK_ANY (gnutls_pk_algorithm_t)-1
 #define GNUTLS_PK_NONE (gnutls_pk_algorithm_t)-2
 
@@ -498,11 +531,53 @@ typedef struct
   int free_rsa_params;
 } internal_params_st;
 
+struct dtls_hsk_retransmit_buffer;
+typedef struct dtls_hsk_retransmit_buffer dtls_hsk_retransmit_buffer;
+
+/* This is a linked list used to buffer the next flight of outgoing
+   handshake messages. Messages are queued whole; they are fragmented
+   dynamically on transmit. */
+struct dtls_hsk_retransmit_buffer
+{
+  dtls_hsk_retransmit_buffer *next;
+
+  /* The actual handshake message */
+  gnutls_datum_t msg;
+
+  /* Record layer epoch of message */
+  uint16_t epoch;
+
+  /* Handshake layer type and sequence of message */
+  gnutls_handshake_description_t type;
+  uint16_t sequence;
+};
+
+/* DTLS session state
+ */
+typedef struct
+{
+  /* HelloVerifyRequest DOS prevention cookie */
+  opaque  cookie[DTLS_MAX_COOKIE_SIZE];
+  uint8_t cookie_len;
+
+  gnutls_dtls_flags_t flags;
+
+  /* For DTLS handshake fragmentation and reassembly. */
+  uint16_t hsk_write_seq;
+  uint16_t hsk_read_seq;
+  uint16_t hsk_mtu;
+
+  /* Head of the next outgoing flight. */
+  dtls_hsk_retransmit_buffer *retransmit;
+  dtls_hsk_retransmit_buffer **retransmit_end;
+
+  unsigned int hsk_hello_verify_requests;
+} dtls_st;
 
 
 typedef struct
 {
-  opaque header[HANDSHAKE_HEADER_SIZE];
+  opaque header[MAX_HANDSHAKE_HEADER_SIZE];
   /* this holds the number of bytes in the handshake_header[] */
   size_t header_size;
   /* this holds the length of the handshake packet */
@@ -755,6 +830,11 @@ typedef struct
     extension_priv_data_t priv;
     int set:1;
   } resumed_extension_int_data[MAX_EXT_TYPES];
+  /* The type of transport protocol; stream or datagram */
+  transport_t transport;
+
+  /* DTLS session state */
+  dtls_st dtls;
 
   unsigned int cb_tls_unique_len;
   unsigned char cb_tls_unique[MAX_VERIFY_DATA_SIZE];
diff --git a/lib/gnutls_kx.c b/lib/gnutls_kx.c
index 24e0b83..d105c16 100644
--- a/lib/gnutls_kx.c
+++ b/lib/gnutls_kx.c
@@ -58,7 +58,7 @@ send_handshake (gnutls_session_t session, opaque * data, 
size_t size,
       return GNUTLS_E_INVALID_REQUEST;
     }
 
-  bufel = _gnutls_handshake_alloc (size, size);
+  bufel = _gnutls_handshake_alloc(session, size, size);
   if (bufel == NULL)
     {
       gnutls_assert ();
diff --git a/lib/gnutls_mbuffers.h b/lib/gnutls_mbuffers.h
index 99b0add..6b3f424 100644
--- a/lib/gnutls_mbuffers.h
+++ b/lib/gnutls_mbuffers.h
@@ -93,7 +93,7 @@ _mbuffer_set_uhead_size (mbuffer_st * bufel, size_t size)
 
 
 inline static mbuffer_st *
-_gnutls_handshake_alloc (size_t size, size_t maximum)
+_gnutls_handshake_alloc (gnutls_session_t session, size_t size, size_t maximum)
 {
   mbuffer_st *ret = _mbuffer_alloc (HANDSHAKE_HEADER_SIZE + size,
                                     HANDSHAKE_HEADER_SIZE + maximum);
diff --git a/lib/gnutls_num.c b/lib/gnutls_num.c
index 2c75541..786cf4d 100644
--- a/lib/gnutls_num.c
+++ b/lib/gnutls_num.c
@@ -62,6 +62,35 @@ _gnutls_uint64pp (uint64 * x)
   return 0;
 }
 
+/* This function will add one to uint48 x.
+ * Returns 0 on success, or -1 if the uint48 max limit
+ * has been reached.
+ */
+int
+_gnutls_uint48pp (uint48 * x)
+{
+  register int i, y = 0;
+
+  for (i = 5; i >= 0; i--)
+    {
+      y = 0;
+      if (x->i[i] == 0xff)
+       {
+         x->i[i] = 0;
+         y = 1;
+       }
+      else
+       x->i[i]++;
+
+      if (y == 0)
+       break;
+    }
+  if (y != 0)
+    return -1;                 /* over 48 bits! meh... */
+
+  return 0;
+}
+
 uint32_t
 _gnutls_uint24touint32 (uint24 num)
 {
@@ -85,6 +114,20 @@ _gnutls_uint32touint24 (uint32_t num)
 
 }
 
+uint64_t
+_gnutls_uint48touint64 (uint48 num)
+{
+  uint64_t ret=0;
+
+  ((uint8_t *) & ret)[2] = num.i[0];
+  ((uint8_t *) & ret)[3] = num.i[1];
+  ((uint8_t *) & ret)[4] = num.i[2];
+  ((uint8_t *) & ret)[5] = num.i[3];
+  ((uint8_t *) & ret)[6] = num.i[4];
+  ((uint8_t *) & ret)[7] = num.i[5];
+  return ret;
+}
+
 /* data should be at least 3 bytes */
 uint32_t
 _gnutls_read_uint24 (const opaque * data)
@@ -193,3 +236,19 @@ _gnutls_uint64touint32 (const uint64 * num)
 
   return ret;
 }
+
+uint64_t
+_gnutls_read_uint48 (const opaque * data)
+{
+  uint64_t ret;
+  uint48 num;
+
+  memcpy(num.i, data, 6);
+
+  ret = _gnutls_uint48touint64 (num);
+#ifndef WORDS_BIGENDIAN
+  ret = bswap_64 (ret);
+#endif
+
+  return ret;
+}
diff --git a/lib/gnutls_num.h b/lib/gnutls_num.h
index e4658e5..8e8aaea 100644
--- a/lib/gnutls_num.h
+++ b/lib/gnutls_num.h
@@ -32,6 +32,8 @@
 
 uint32_t _gnutls_uint24touint32 (uint24 num);
 uint24 _gnutls_uint32touint24 (uint32_t num);
+uint64_t _gnutls_uint48touint64 (uint48 num);
+uint64_t _gnutls_read_uint48 (const opaque * data);
 uint32_t _gnutls_read_uint32 (const opaque * data);
 uint16_t _gnutls_read_uint16 (const opaque * data);
 uint32_t _gnutls_conv_uint32 (uint32_t data);
@@ -43,7 +45,8 @@ void _gnutls_write_uint16 (uint16_t num, opaque * data);
 uint32_t _gnutls_uint64touint32 (const uint64 *);
 
 int _gnutls_uint64pp (uint64 *);
-#define _gnutls_uint64zero(x) x.i[0] = x.i[1] = x.i[2] = x.i[3] = x.i[4] = 
x.i[5] = x.i[6] = x.i[7] = 0
-#define UINT64DATA(x) (x.i)
+int _gnutls_uint48pp (uint48 *);
+# define _gnutls_uint64zero(x) x.i[0] = x.i[1] = x.i[2] = x.i[3] = x.i[4] = 
x.i[5] = x.i[6] = x.i[7] = 0
+# define UINT64DATA(x) ((x).i)
 
 #endif /* GNUTLS_NUM_H */
diff --git a/lib/gnutls_priority.c b/lib/gnutls_priority.c
index cb2593a..c91b0d3 100644
--- a/lib/gnutls_priority.c
+++ b/lib/gnutls_priority.c
@@ -220,6 +220,7 @@ static const int protocol_priority[] = {
   GNUTLS_TLS1_1,
   GNUTLS_TLS1_0,
   GNUTLS_SSL3,
+  GNUTLS_DTLS1_0,
   0
 };
 
diff --git a/lib/gnutls_record.c b/lib/gnutls_record.c
index 66f85ca..a543b23 100644
--- a/lib/gnutls_record.c
+++ b/lib/gnutls_record.c
@@ -319,6 +319,38 @@ copy_record_version (gnutls_session_t session,
     }
 }
 
+/* Increments the sequence value
+ */
+inline static int
+sequence_increment (gnutls_session_t session,
+                   uint64 * value)
+{
+  if (_gnutls_is_dtls(session))
+    {
+      return _gnutls_uint48pp((uint48*)&value->i[2]);
+    }
+  else
+    {
+      return _gnutls_uint64pp(value);
+    }
+}
+
+/* Read epoch and sequence from a DTLS packet */
+inline static void
+sequence_read (uint64 * sequence,
+              opaque * data)
+{
+  memcpy(sequence->i, data, 8);
+}
+
+/* Write epoch and sequence to a DTLS packet */
+inline static void
+sequence_write (uint64 * sequence,
+               opaque * data)
+{
+  memcpy(data, sequence->i, 8);
+}
+
 /* This function behaves exactly like write(). The only difference is
  * that it accepts, the gnutls_session_t and the content_type_t of data to
  * send (if called by the user the Content is specific)
@@ -343,7 +375,8 @@ _gnutls_send_int (gnutls_session_t session, content_type_t 
type,
   size_t cipher_size;
   int retval, ret;
   int data2send_size;
-  uint8_t headers[5];
+  uint8_t headers[MAX_RECORD_HEADER_SIZE];
+  int header_size;
   const uint8_t *data = _data;
   record_parameters_st *record_params;
   record_state_st *record_state;
@@ -389,6 +422,9 @@ _gnutls_send_int (gnutls_session_t session, content_type_t 
type,
    */
   copy_record_version (session, htype, &headers[1]);
 
+  header_size = RECORD_HEADER_SIZE;
+  /* Adjust header length and add sequence for DTLS */
+    sequence_write(&record_state->sequence_number, &headers[3]);
 
   _gnutls_record_log
     ("REC[%p]: Sending Packet[%d] %s(%d) with length: %d\n", session,
@@ -427,7 +463,7 @@ _gnutls_send_int (gnutls_session_t session, content_type_t 
type,
         }
 
       cipher_size =
-        _gnutls_encrypt (session, headers, RECORD_HEADER_SIZE, data,
+        _gnutls_encrypt (session, headers, header_size, data,
                          data2send_size, _mbuffer_get_udata_ptr (bufel),
                          cipher_size, type,
                          (session->internals.priorities.no_padding ==
@@ -446,7 +482,7 @@ _gnutls_send_int (gnutls_session_t session, content_type_t 
type,
 
       /* increase sequence number
        */
-      if (_gnutls_uint64pp (&record_state->sequence_number) != 0)
+      if (sequence_increment (session, &record_state->sequence_number) != 0)
         {
           session_invalidate (session);
           gnutls_assert ();
@@ -572,11 +608,12 @@ check_buffers (gnutls_session_t session, content_type_t 
type,
  */
 static int
 record_check_headers (gnutls_session_t session,
-                      uint8_t headers[RECORD_HEADER_SIZE],
+                      uint8_t headers[MAX_RECORD_HEADER_SIZE],
                       content_type_t type,
                       gnutls_handshake_description_t htype,
                       /*output */ content_type_t * recv_type,
-                      opaque version[2], uint16_t * length,
+                      opaque version[2], uint64* sequence,
+                      uint16_t * length,
                       uint16_t * header_size)
 {
 
@@ -610,6 +647,17 @@ record_check_headers (gnutls_session_t session,
                           session, *length);
 
     }
+  else if(_gnutls_is_dtls(session))
+    {
+      /* dtls version 1.0 */
+      *recv_type = headers[0];
+      version[0] = headers[1];
+      version[1] = headers[2];
+
+      sequence_read(sequence, &headers[3]);
+
+      *length = _gnutls_read_uint16 (&headers[11]);
+    }
   else
     {
       /* version 3.x 
@@ -872,6 +920,8 @@ _gnutls_recv_int (gnutls_session_t session, content_type_t 
type,
 {
   int decrypted_length;
   opaque version[2];
+  uint64 dtls_sequence;
+  uint64 *decrypt_sequence;
   content_type_t recv_type;
   uint16_t length;
   uint8_t *ciphertext;
@@ -882,22 +932,6 @@ _gnutls_recv_int (gnutls_session_t session, content_type_t 
type,
   record_parameters_st *record_params;
   record_state_st *record_state;
 
-  ret = _gnutls_epoch_get (session, EPOCH_READ_CURRENT, &record_params);
-  if (ret < 0)
-    {
-      gnutls_assert ();
-      return ret;
-    }
-
-  /* Safeguard against processing data with an incomplete cipher state. */
-  if (!record_params->initialized)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_INVALID_REQUEST;
-    }
-
-  record_state = &record_params->read;
-
   if (type != GNUTLS_ALERT && (sizeofdata == 0 || data == NULL))
     {
       return GNUTLS_E_INVALID_REQUEST;
@@ -968,12 +1002,22 @@ begin:
 
   if ((ret =
        record_check_headers (session, data_enc.data, type, htype, &recv_type,
-                             version, &length, &header_size)) < 0)
+                            version, &dtls_sequence, &length, &header_size)) < 
0)
     {
       gnutls_assert ();
       return ret;
     }
 
+  ret = _gnutls_epoch_get (session, EPOCH_READ_CURRENT, &record_params);
+  if (ret < 0)
+    return gnutls_assert_val (ret);
+
+  /* Safeguard against processing data with an incomplete cipher state. */
+  if (!record_params->initialized)
+    return gnutls_assert_val (GNUTLS_E_INVALID_REQUEST);
+
+  record_state = &record_params->read;
+
 /* Here we check if the Type of the received packet is
  * ok. 
  */
@@ -1050,11 +1094,14 @@ begin:
       return ret;
     }
 
+  decrypt_sequence =
+    _gnutls_is_dtls(session) ? &dtls_sequence : &record_state->sequence_number;
+
 /* decrypt the data we got. 
  */
   ret =
     _gnutls_decrypt (session, ciphertext, length, tmp.data, tmp.size,
-                     recv_type, record_params);
+                    recv_type, record_params, decrypt_sequence);
   if (ret < 0)
     {
       session_unresumable (session);
@@ -1092,7 +1139,7 @@ begin:
 
 /* increase sequence number 
  */
-  if (_gnutls_uint64pp (&record_state->sequence_number) != 0)
+  if (sequence_increment (session, &record_state->sequence_number) != 0)
     {
       session_invalidate (session);
       gnutls_assert ();
diff --git a/lib/gnutls_state.c b/lib/gnutls_state.c
index 3e08f9b..afdbb02 100644
--- a/lib/gnutls_state.c
+++ b/lib/gnutls_state.c
@@ -363,6 +363,40 @@ gnutls_init (gnutls_session_t * session, 
gnutls_connection_end_t con_end)
   return 0;
 }
 
+/**
+  * gnutls_init_dtls - initialize the session like gnutls_init, but
+  * with a DTLS compatible transport.
+  * @con_end: indicate if this session is to be used for server or client.
+  * @session: is a pointer to a #gnutls_session_t structure.
+  * @flags: dtls flags for optional behavior.
+  *
+  * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
+  **/
+int
+gnutls_init_dtls (gnutls_session_t * session,
+                 gnutls_connection_end_t con_end,
+                 gnutls_dtls_flags_t flags)
+{
+  int ret;
+
+  /* FIXME, we should inhibit the allocation of many buffers that are
+     useless with datagram transport. */
+  ret = gnutls_init(session, con_end);
+
+  if(ret != 0)
+    return ret;
+
+  /* Flags do nothing, so just copy them into the struct for now. */
+  (*session)->internals.dtls.flags = flags;
+  (*session)->internals.dtls.hsk_mtu = DTLS_DEFAULT_MTU;
+  (*session)->internals.transport = GNUTLS_DGRAM;
+
+  /* Initialize pointer used to enqueue messages for retransmit. */
+  (*session)->internals.dtls.retransmit_end = 
&(*session)->internals.dtls.retransmit;
+
+  return 0;
+}
+
 /* returns RESUME_FALSE or RESUME_TRUE.
  */
 int
diff --git a/lib/gnutls_state.h b/lib/gnutls_state.h
index 2112cd5..995b4a7 100644
--- a/lib/gnutls_state.h
+++ b/lib/gnutls_state.h
@@ -71,3 +71,17 @@ int _gnutls_PRF (gnutls_session_t session,
                  int total_bytes, void *ret);
 
 #define DEFAULT_CERT_TYPE GNUTLS_CRT_X509
+
+/*-
+ * _gnutls_is_dtls - Used to check whether this session uses DTLS.
+ * @session: is a #gnutls_session_t structure.
+ *
+ * This function will return non zero if this session uses DTLS.
+ *
+ -*/
+static inline
+int
+_gnutls_is_dtls (gnutls_session_t session)
+{
+  return session->internals.transport == GNUTLS_DGRAM;
+}
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index 0a3ec6c..581acf3 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -300,6 +300,13 @@ extern "C"
    */
   typedef enum
   {
+    /* Nothing for now. There will be flags for transport-dependent
+       behavior (DCCP, SCTP) here in the future. */
+    GNUTLS_DTLS_DUMMY = 0
+  } gnutls_dtls_flags_t;
+
+  typedef enum
+  {
     GNUTLS_AL_WARNING = 1,
     GNUTLS_AL_FATAL
   } gnutls_alert_level_t;
@@ -397,6 +404,7 @@ extern "C"
     GNUTLS_HANDSHAKE_HELLO_REQUEST = 0,
     GNUTLS_HANDSHAKE_CLIENT_HELLO = 1,
     GNUTLS_HANDSHAKE_SERVER_HELLO = 2,
+    GNUTLS_HANDSHAKE_HELLO_VERIFY_REQUEST = 3,
     GNUTLS_HANDSHAKE_NEW_SESSION_TICKET = 4,
     GNUTLS_HANDSHAKE_CERTIFICATE_PKT = 11,
     GNUTLS_HANDSHAKE_SERVER_KEY_EXCHANGE = 12,
@@ -486,6 +494,7 @@ extern "C"
    * @GNUTLS_TLS1: Same as %GNUTLS_TLS1_0.
    * @GNUTLS_TLS1_1: TLS version 1.1.
    * @GNUTLS_TLS1_2: TLS version 1.2.
+   * @GNUTLS_DTLS1_0: DTLS version 1.0.
    * @GNUTLS_VERSION_MAX: Maps to the highest supported TLS version.
    * @GNUTLS_VERSION_UNKNOWN: Unknown SSL/TLS version.
    *
@@ -498,7 +507,8 @@ extern "C"
     GNUTLS_TLS1 = GNUTLS_TLS1_0,
     GNUTLS_TLS1_1 = 3,
     GNUTLS_TLS1_2 = 4,
-    GNUTLS_VERSION_MAX = GNUTLS_TLS1_2,
+    GNUTLS_DTLS1_0 = 5,
+    GNUTLS_VERSION_MAX = GNUTLS_DTLS1_0,
     GNUTLS_VERSION_UNKNOWN = 0xff
   } gnutls_protocol_t;
 
@@ -676,6 +686,9 @@ extern "C"
 
   int gnutls_init (gnutls_session_t * session,
                    gnutls_connection_end_t con_end);
+  int gnutls_init_dtls (gnutls_session_t * session,
+                       gnutls_connection_end_t con_end,
+                       gnutls_dtls_flags_t flags);
   void gnutls_deinit (gnutls_session_t session);
 #define _gnutls_deinit(x) gnutls_deinit(x)
 
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index 1dda938..945b45d 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -153,6 +153,7 @@ GNUTLS_1_4
     gnutls_hex_decode;
     gnutls_hex_encode;
     gnutls_init;
+    gnutls_init_dtls;
     gnutls_kx_get;
     gnutls_kx_get_id;
     gnutls_kx_get_name;
diff --git a/src/cli-gaa.c b/src/cli-gaa.c
index dae1c07..aab764e 100644
--- a/src/cli-gaa.c
+++ b/src/cli-gaa.c
@@ -130,8 +130,9 @@ void gaa_help(void)
        __gaa_helpsingle('d', "debug", "integer ", "Enable debugging");
        __gaa_helpsingle('r', "resume", "", "Connect, establish a session. 
Connect again and resume this session.");
        __gaa_helpsingle('e', "rehandshake", "", "Connect, establish a session 
and rehandshake immediately.");
-       __gaa_helpsingle(0, "noticket", "", "Doen't accept session tickets.");
+       __gaa_helpsingle(0, "noticket", "", "Doesn't accept session tickets.");
        __gaa_helpsingle('s', "starttls", "", "Connect, establish a plain 
session and start TLS when EOF or a SIGALRM is received.");
+       __gaa_helpsingle('u', "dtls", "", "Use DTLS (datagram TLS).");
        __gaa_helpsingle(0, "crlf", "", "Send CR LF instead of LF.");
        __gaa_helpsingle(0, "x509fmtder", "", "Use DER format for certificates 
to read from.");
        __gaa_helpsingle('f', "fingerprint", "", "Send the openpgp fingerprint, 
instead of the key.");
@@ -171,52 +172,54 @@ typedef struct _gaainfo gaainfo;
 
 struct _gaainfo
 {
-#line 100 "cli.gaa"
+#line 103 "cli.gaa"
        char *rest_args;
-#line 92 "cli.gaa"
+#line 95 "cli.gaa"
        int insecure;
-#line 89 "cli.gaa"
+#line 92 "cli.gaa"
        char *port;
-#line 86 "cli.gaa"
+#line 89 "cli.gaa"
        char *psk_key;
-#line 83 "cli.gaa"
+#line 86 "cli.gaa"
        char *psk_username;
-#line 80 "cli.gaa"
+#line 83 "cli.gaa"
        char *srp_passwd;
-#line 77 "cli.gaa"
+#line 80 "cli.gaa"
        char *srp_username;
-#line 74 "cli.gaa"
+#line 77 "cli.gaa"
        char *x509_certfile;
-#line 71 "cli.gaa"
+#line 74 "cli.gaa"
        char *x509_keyfile;
-#line 68 "cli.gaa"
+#line 71 "cli.gaa"
        char *pgp_subkey;
-#line 65 "cli.gaa"
+#line 68 "cli.gaa"
        char *pgp_certfile;
-#line 62 "cli.gaa"
+#line 65 "cli.gaa"
        char *pgp_keyring;
-#line 59 "cli.gaa"
+#line 62 "cli.gaa"
        char *pgp_keyfile;
-#line 56 "cli.gaa"
+#line 59 "cli.gaa"
        char *x509_crlfile;
-#line 53 "cli.gaa"
+#line 56 "cli.gaa"
        char *x509_cafile;
-#line 50 "cli.gaa"
+#line 53 "cli.gaa"
        char *priorities;
-#line 47 "cli.gaa"
+#line 50 "cli.gaa"
        int verbose;
-#line 44 "cli.gaa"
+#line 47 "cli.gaa"
        int record_size;
-#line 41 "cli.gaa"
+#line 44 "cli.gaa"
        int print_cert;
-#line 38 "cli.gaa"
+#line 41 "cli.gaa"
        int disable_extensions;
-#line 35 "cli.gaa"
+#line 38 "cli.gaa"
        int fingerprint;
-#line 32 "cli.gaa"
+#line 35 "cli.gaa"
        int fmtder;
-#line 29 "cli.gaa"
+#line 32 "cli.gaa"
        int crlf;
+#line 29 "cli.gaa"
+       int dtls;
 #line 26 "cli.gaa"
        int starttls;
 #line 23 "cli.gaa"
@@ -281,7 +284,7 @@ static int gaa_error = 0;
 #define GAA_MULTIPLE_OPTION     3
 
 #define GAA_REST                0
-#define GAA_NB_OPTION           30
+#define GAA_NB_OPTION           31
 #define GAAOPTID_version       1
 #define GAAOPTID_help  2
 #define GAAOPTID_list  3
@@ -307,11 +310,12 @@ static int gaa_error = 0;
 #define GAAOPTID_fingerprint   23
 #define GAAOPTID_x509fmtder    24
 #define GAAOPTID_crlf  25
-#define GAAOPTID_starttls      26
-#define GAAOPTID_noticket      27
-#define GAAOPTID_rehandshake   28
-#define GAAOPTID_resume        29
-#define GAAOPTID_debug 30
+#define GAAOPTID_dtls  26
+#define GAAOPTID_starttls      27
+#define GAAOPTID_noticket      28
+#define GAAOPTID_rehandshake   29
+#define GAAOPTID_resume        30
+#define GAAOPTID_debug 31
 
 #line 168 "gaa.skel"
 
@@ -658,6 +662,7 @@ static int gaa_get_option_num(char *str, int status)
                        GAA_CHECK1STR("f", GAAOPTID_fingerprint);
                        GAA_CHECK1STR("", GAAOPTID_x509fmtder);
                        GAA_CHECK1STR("", GAAOPTID_crlf);
+                       GAA_CHECK1STR("u", GAAOPTID_dtls);
                        GAA_CHECK1STR("s", GAAOPTID_starttls);
                        GAA_CHECK1STR("", GAAOPTID_noticket);
                        GAA_CHECK1STR("e", GAAOPTID_rehandshake);
@@ -691,6 +696,7 @@ static int gaa_get_option_num(char *str, int status)
                        GAA_CHECKSTR("fingerprint", GAAOPTID_fingerprint);
                        GAA_CHECKSTR("x509fmtder", GAAOPTID_x509fmtder);
                        GAA_CHECKSTR("crlf", GAAOPTID_crlf);
+                       GAA_CHECKSTR("dtls", GAAOPTID_dtls);
                        GAA_CHECKSTR("starttls", GAAOPTID_starttls);
                        GAA_CHECKSTR("noticket", GAAOPTID_noticket);
                        GAA_CHECKSTR("rehandshake", GAAOPTID_rehandshake);
@@ -746,28 +752,28 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
     {
        case GAAOPTID_version:
        OK = 0;
-#line 98 "cli.gaa"
+#line 101 "cli.gaa"
 { cli_version(); exit(0); ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_help:
        OK = 0;
-#line 96 "cli.gaa"
+#line 99 "cli.gaa"
 { gaa_help(); exit(0); ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_list:
        OK = 0;
-#line 95 "cli.gaa"
+#line 98 "cli.gaa"
 { print_list(gaaval->verbose); exit(0); ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_insecure:
        OK = 0;
-#line 93 "cli.gaa"
+#line 96 "cli.gaa"
 { gaaval->insecure = 1 ;};
 
                return GAA_OK;
@@ -777,7 +783,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAATMP_port.arg1, gaa_getstr, GAATMP_port.size1);
                gaa_index++;
-#line 90 "cli.gaa"
+#line 93 "cli.gaa"
 { gaaval->port = GAATMP_port.arg1 ;};
 
                return GAA_OK;
@@ -787,7 +793,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAATMP_pskkey.arg1, gaa_getstr, GAATMP_pskkey.size1);
                gaa_index++;
-#line 87 "cli.gaa"
+#line 90 "cli.gaa"
 { gaaval->psk_key = GAATMP_pskkey.arg1 ;};
 
                return GAA_OK;
@@ -797,7 +803,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAATMP_pskusername.arg1, gaa_getstr, 
GAATMP_pskusername.size1);
                gaa_index++;
-#line 84 "cli.gaa"
+#line 87 "cli.gaa"
 { gaaval->psk_username = GAATMP_pskusername.arg1 ;};
 
                return GAA_OK;
@@ -807,7 +813,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAATMP_srppasswd.arg1, gaa_getstr, 
GAATMP_srppasswd.size1);
                gaa_index++;
-#line 81 "cli.gaa"
+#line 84 "cli.gaa"
 { gaaval->srp_passwd = GAATMP_srppasswd.arg1 ;};
 
                return GAA_OK;
@@ -817,7 +823,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAATMP_srpusername.arg1, gaa_getstr, 
GAATMP_srpusername.size1);
                gaa_index++;
-#line 78 "cli.gaa"
+#line 81 "cli.gaa"
 { gaaval->srp_username = GAATMP_srpusername.arg1 ;};
 
                return GAA_OK;
@@ -827,7 +833,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAATMP_x509certfile.arg1, gaa_getstr, 
GAATMP_x509certfile.size1);
                gaa_index++;
-#line 75 "cli.gaa"
+#line 78 "cli.gaa"
 { gaaval->x509_certfile = GAATMP_x509certfile.arg1 ;};
 
                return GAA_OK;
@@ -837,7 +843,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAATMP_x509keyfile.arg1, gaa_getstr, 
GAATMP_x509keyfile.size1);
                gaa_index++;
-#line 72 "cli.gaa"
+#line 75 "cli.gaa"
 { gaaval->x509_keyfile = GAATMP_x509keyfile.arg1 ;};
 
                return GAA_OK;
@@ -847,7 +853,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAATMP_pgpsubkey.arg1, gaa_getstr, 
GAATMP_pgpsubkey.size1);
                gaa_index++;
-#line 69 "cli.gaa"
+#line 72 "cli.gaa"
 { gaaval->pgp_subkey = GAATMP_pgpsubkey.arg1 ;};
 
                return GAA_OK;
@@ -857,7 +863,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAATMP_pgpcertfile.arg1, gaa_getstr, 
GAATMP_pgpcertfile.size1);
                gaa_index++;
-#line 66 "cli.gaa"
+#line 69 "cli.gaa"
 { gaaval->pgp_certfile = GAATMP_pgpcertfile.arg1 ;};
 
                return GAA_OK;
@@ -867,7 +873,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAATMP_pgpkeyring.arg1, gaa_getstr, 
GAATMP_pgpkeyring.size1);
                gaa_index++;
-#line 63 "cli.gaa"
+#line 66 "cli.gaa"
 { gaaval->pgp_keyring = GAATMP_pgpkeyring.arg1 ;};
 
                return GAA_OK;
@@ -877,7 +883,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAATMP_pgpkeyfile.arg1, gaa_getstr, 
GAATMP_pgpkeyfile.size1);
                gaa_index++;
-#line 60 "cli.gaa"
+#line 63 "cli.gaa"
 { gaaval->pgp_keyfile = GAATMP_pgpkeyfile.arg1 ;};
 
                return GAA_OK;
@@ -887,7 +893,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAATMP_x509crlfile.arg1, gaa_getstr, 
GAATMP_x509crlfile.size1);
                gaa_index++;
-#line 57 "cli.gaa"
+#line 60 "cli.gaa"
 { gaaval->x509_crlfile = GAATMP_x509crlfile.arg1 ;};
 
                return GAA_OK;
@@ -897,7 +903,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAATMP_x509cafile.arg1, gaa_getstr, 
GAATMP_x509cafile.size1);
                gaa_index++;
-#line 54 "cli.gaa"
+#line 57 "cli.gaa"
 { gaaval->x509_cafile = GAATMP_x509cafile.arg1 ;};
 
                return GAA_OK;
@@ -907,14 +913,14 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAATMP_priority.arg1, gaa_getstr, 
GAATMP_priority.size1);
                gaa_index++;
-#line 51 "cli.gaa"
+#line 54 "cli.gaa"
 { gaaval->priorities = GAATMP_priority.arg1 ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_verbose:
        OK = 0;
-#line 48 "cli.gaa"
+#line 51 "cli.gaa"
 { gaaval->verbose = 1 ;};
 
                return GAA_OK;
@@ -924,46 +930,53 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAATMP_recordsize.arg1, gaa_getint, 
GAATMP_recordsize.size1);
                gaa_index++;
-#line 45 "cli.gaa"
+#line 48 "cli.gaa"
 { gaaval->record_size = GAATMP_recordsize.arg1 ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_print_cert:
        OK = 0;
-#line 42 "cli.gaa"
+#line 45 "cli.gaa"
 { gaaval->print_cert = 1 ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_disable_extensions:
        OK = 0;
-#line 39 "cli.gaa"
+#line 42 "cli.gaa"
 { gaaval->disable_extensions = 1 ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_fingerprint:
        OK = 0;
-#line 36 "cli.gaa"
+#line 39 "cli.gaa"
 { gaaval->fingerprint = 1 ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_x509fmtder:
        OK = 0;
-#line 33 "cli.gaa"
+#line 36 "cli.gaa"
 { gaaval->fmtder = 1 ;};
 
                return GAA_OK;
                break;
        case GAAOPTID_crlf:
        OK = 0;
-#line 30 "cli.gaa"
+#line 33 "cli.gaa"
 { gaaval->crlf = 1 ;};
 
                return GAA_OK;
                break;
+       case GAAOPTID_dtls:
+       OK = 0;
+#line 30 "cli.gaa"
+{ gaaval->dtls = 1 ;};
+
+               return GAA_OK;
+               break;
        case GAAOPTID_starttls:
        OK = 0;
 #line 27 "cli.gaa"
@@ -1006,7 +1019,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo 
*gaaval, char *opt_list)
                GAA_TESTMOREARGS;
                GAA_FILL(GAAREST_tmp.arg1, gaa_getstr, GAAREST_tmp.size1);
                gaa_index++;
-#line 101 "cli.gaa"
+#line 104 "cli.gaa"
 { gaaval->rest_args = GAAREST_tmp.arg1; ;};
 
                return GAA_OK;
@@ -1035,7 +1048,7 @@ int gaa(int argc, char **argv, gaainfo *gaaval)
     if(inited == 0)
     {
 
-#line 103 "cli.gaa"
+#line 106 "cli.gaa"
 { gaaval->resume=0; gaaval->noticket=0; gaaval->port="443"; 
gaaval->rest_args=NULL; 
        gaaval->record_size=0; 
        gaaval->fingerprint=0; gaaval->pgp_keyring=NULL; gaaval->x509_crlfile = 
NULL;
@@ -1044,7 +1057,7 @@ int gaa(int argc, char **argv, gaainfo *gaaval)
        gaaval->srp_username=NULL; gaaval->srp_passwd=NULL; gaaval->fmtder = 0; 
gaaval->starttls =0; 
        gaaval->debug = 0; gaaval->print_cert = 0; gaaval->verbose = 0; 
gaaval->psk_key = NULL; 
        gaaval->psk_username = NULL; gaaval->priorities = NULL;
-       gaaval->pgp_subkey = NULL; gaaval->rehandshake = 0; ;};
+       gaaval->pgp_subkey = NULL; gaaval->rehandshake = 0; gaaval->dtls = 0; 
;};
 
     }
     inited = 1;
diff --git a/src/cli-gaa.h b/src/cli-gaa.h
index 833f534..07f409b 100644
--- a/src/cli-gaa.h
+++ b/src/cli-gaa.h
@@ -8,52 +8,54 @@ typedef struct _gaainfo gaainfo;
 
 struct _gaainfo
 {
-#line 100 "cli.gaa"
+#line 103 "cli.gaa"
        char *rest_args;
-#line 92 "cli.gaa"
+#line 95 "cli.gaa"
        int insecure;
-#line 89 "cli.gaa"
+#line 92 "cli.gaa"
        char *port;
-#line 86 "cli.gaa"
+#line 89 "cli.gaa"
        char *psk_key;
-#line 83 "cli.gaa"
+#line 86 "cli.gaa"
        char *psk_username;
-#line 80 "cli.gaa"
+#line 83 "cli.gaa"
        char *srp_passwd;
-#line 77 "cli.gaa"
+#line 80 "cli.gaa"
        char *srp_username;
-#line 74 "cli.gaa"
+#line 77 "cli.gaa"
        char *x509_certfile;
-#line 71 "cli.gaa"
+#line 74 "cli.gaa"
        char *x509_keyfile;
-#line 68 "cli.gaa"
+#line 71 "cli.gaa"
        char *pgp_subkey;
-#line 65 "cli.gaa"
+#line 68 "cli.gaa"
        char *pgp_certfile;
-#line 62 "cli.gaa"
+#line 65 "cli.gaa"
        char *pgp_keyring;
-#line 59 "cli.gaa"
+#line 62 "cli.gaa"
        char *pgp_keyfile;
-#line 56 "cli.gaa"
+#line 59 "cli.gaa"
        char *x509_crlfile;
-#line 53 "cli.gaa"
+#line 56 "cli.gaa"
        char *x509_cafile;
-#line 50 "cli.gaa"
+#line 53 "cli.gaa"
        char *priorities;
-#line 47 "cli.gaa"
+#line 50 "cli.gaa"
        int verbose;
-#line 44 "cli.gaa"
+#line 47 "cli.gaa"
        int record_size;
-#line 41 "cli.gaa"
+#line 44 "cli.gaa"
        int print_cert;
-#line 38 "cli.gaa"
+#line 41 "cli.gaa"
        int disable_extensions;
-#line 35 "cli.gaa"
+#line 38 "cli.gaa"
        int fingerprint;
-#line 32 "cli.gaa"
+#line 35 "cli.gaa"
        int fmtder;
-#line 29 "cli.gaa"
+#line 32 "cli.gaa"
        int crlf;
+#line 29 "cli.gaa"
+       int dtls;
 #line 26 "cli.gaa"
        int starttls;
 #line 23 "cli.gaa"
diff --git a/src/cli.c b/src/cli.c
index 3ea3906..762146c 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -53,7 +53,7 @@
 #define MAX_BUF 4096
 
 /* global stuff here */
-int resume, starttls, insecure, rehandshake;
+int resume, starttls, insecure, rehandshake, dtls;
 const char *hostname = NULL;
 char *service;
 int record_max_size;
@@ -551,7 +551,10 @@ init_tls_session (const char *hostname)
 
   gnutls_session_t session;
 
-  gnutls_init (&session, GNUTLS_CLIENT);
+  if (dtls)
+    gnutls_init_dtls (&session, GNUTLS_CLIENT, 0);
+  else
+    gnutls_init (&session, GNUTLS_CLIENT);
 
   if (gnutls_priority_set_direct (session, info.priorities, &err) < 0)
     {
@@ -974,6 +977,7 @@ gaa_parser (int argc, char **argv)
   resume = info.resume;
   rehandshake = info.rehandshake;
   insecure = info.insecure;
+  dtls = info.dtls;
   service = info.port;
   record_max_size = info.record_size;
   fingerprint = info.fingerprint;
@@ -1392,7 +1396,7 @@ socket_open (socket_st * hd, const char *hostname, const 
char *service)
   printf ("Resolving '%s'...\n", hostname);
   /* get server name */
   memset (&hints, 0, sizeof (hints));
-  hints.ai_socktype = SOCK_STREAM;
+  hints.ai_socktype = dtls ? SOCK_DGRAM : SOCK_STREAM;
   if ((err = getaddrinfo (hostname, service, &hints, &res)))
     {
       fprintf (stderr, "Cannot resolve %s:%s: %s\n", hostname, service,
diff --git a/src/cli.gaa b/src/cli.gaa
index efd7e32..c7de095 100644
--- a/src/cli.gaa
+++ b/src/cli.gaa
@@ -21,11 +21,14 @@ option (r, resume) { $resume = 1 } "Connect, establish a 
session. Connect again
 option (e, rehandshake) { $rehandshake = 1 } "Connect, establish a session and 
rehandshake immediately."
 
 #int noticket;
-option (noticket) { $noticket = 1 } "Doen't accept session tickets."
+option (noticket) { $noticket = 1 } "Doesn't accept session tickets."
 
 #int starttls;
 option (s, starttls) { $starttls = 1 } "Connect, establish a plain session and 
start TLS when EOF or a SIGALRM is received."
 
+#int dtls;
+option (u, dtls) { $dtls = 1 } "Use DTLS (datagram TLS)."
+
 #int crlf;
 option (crlf) { $crlf = 1 } "Send CR LF instead of LF."
 
@@ -108,4 +111,4 @@ init { $resume=0; $noticket=0; $port="443"; $rest_args=NULL;
        $srp_username=NULL; $srp_passwd=NULL; $fmtder = 0; $starttls =0; 
        $debug = 0; $print_cert = 0; $verbose = 0; $psk_key = NULL; 
        $psk_username = NULL; $priorities = NULL;
-       $pgp_subkey = NULL; $rehandshake = 0; }
+       $pgp_subkey = NULL; $rehandshake = 0; $dtls = 0; }


hooks/post-receive
-- 
GNU gnutls



reply via email to

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