* @author Christian Grothoff
*
* FIXME:
- * - implement keepalive
- * - implement rekeying
- * - check KX estate machine -- make sure it is never stuck!
- * - clean up KX logic, including adding sender authentication
- * - implement connection management (evaluate, kill old ones,
- * search for new ones)
- * - when managing connections, distinguish those that
- * have (recently) had traffic from those that were
- * never ready (or not recently)
+ * - KX:
+ * + clean up KX logic, including adding sender authentication
+ * + implement rekeying
+ * + check KX estate machine -- make sure it is never stuck!
+ * - connection management
+ * + properly (evaluate, kill old ones, search for new ones)
+ * + when managing connections, distinguish those that
+ * have (recently) had traffic from those that were
+ * never ready (or not recently)
*/
#include "platform.h"
#include "gnunet_util_lib.h"
*/
#define IDLE_DESTROY_DELAY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 90)
-/**
- * Yuck, replace by 'offsetof' expression?
- * FIXME.
- */
-#define AX_HEADER_SIZE (sizeof (uint32_t) * 2\
- + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey))
-
-
/**
* Maximum number of skipped keys we keep in memory per tunnel.
*/
*/
struct CadetTunnelQueueEntry *tq_tail;
-
- /**
- * Ephemeral message in the queue (to avoid queueing more than one).
- */
- struct CadetConnectionQueue *ephm_hKILL;
-
- /**
- * Pong message in the queue.
- */
- struct CadetConnectionQueue *pong_hKILL;
-
/**
* How long do we wait until we retry the KX?
*/
key, sizeof (*key),
ctx, sizeof (ctx),
NULL);
- /* Two step: CADET_Hash is only 256 bits, HashCode is 512. */
+ /* Two step: GNUNET_ShortHash is only 256 bits,
+ GNUNET_HashCode is 512, so we truncate. */
GNUNET_CRYPTO_hmac (&auth_key,
plaintext,
size,
&ax->HKs,
NULL, 0,
NULL);
- out_size = GNUNET_CRYPTO_symmetric_encrypt (&msg->Ns,
- AX_HEADER_SIZE,
+ out_size = GNUNET_CRYPTO_symmetric_encrypt (&msg->ax_header.Ns,
+ sizeof (struct GNUNET_CADET_AxHeader),
&ax->HKs,
&iv,
- &msg->Ns);
- GNUNET_assert (AX_HEADER_SIZE == out_size);
+ &msg->ax_header.Ns);
+ GNUNET_assert (sizeof (struct GNUNET_CADET_AxHeader) == out_size);
}
&ax->HKr,
NULL, 0,
NULL);
- out_size = GNUNET_CRYPTO_symmetric_decrypt (&src->Ns,
- AX_HEADER_SIZE,
+ out_size = GNUNET_CRYPTO_symmetric_decrypt (&src->ax_header.Ns,
+ sizeof (struct GNUNET_CADET_AxHeader),
&ax->HKr,
&iv,
- &dst->Ns);
- GNUNET_assert (AX_HEADER_SIZE == out_size);
+ &dst->ax_header.Ns);
+ GNUNET_assert (sizeof (struct GNUNET_CADET_AxHeader) == out_size);
}
valid_HK = NULL;
for (key = t->ax.skipped_head; NULL != key; key = key->next)
{
- t_hmac (&src->Ns,
- AX_HEADER_SIZE + esize,
+ t_hmac (&src->ax_header,
+ sizeof (struct GNUNET_CADET_AxHeader) + esize,
0,
&key->HK,
hmac);
&key->HK,
NULL, 0,
NULL);
- res = GNUNET_CRYPTO_symmetric_decrypt (&src->Ns,
- AX_HEADER_SIZE,
+ res = GNUNET_CRYPTO_symmetric_decrypt (&src->ax_header.Ns,
+ sizeof (struct GNUNET_CADET_AxHeader),
&key->HK,
&iv,
- &plaintext_header.Ns);
- GNUNET_assert (AX_HEADER_SIZE == res);
+ &plaintext_header.ax_header.Ns);
+ GNUNET_assert (sizeof (struct GNUNET_CADET_AxHeader) == res);
/* Find the correct message key */
- N = ntohl (plaintext_header.Ns);
+ N = ntohl (plaintext_header.ax_header.Ns);
while ( (NULL != key) &&
(N != key->Kn) )
key = key->next;
ax = &t->ax;
/* Try current HK */
- t_hmac (&src->Ns,
- AX_HEADER_SIZE + esize,
+ t_hmac (&src->ax_header,
+ sizeof (struct GNUNET_CADET_AxHeader) + esize,
0, &ax->HKr,
&msg_hmac);
if (0 != memcmp (&msg_hmac,
struct GNUNET_CRYPTO_EcdhePublicKey *DHRp;
/* Try Next HK */
- t_hmac (&src->Ns,
- AX_HEADER_SIZE + esize,
+ t_hmac (&src->ax_header,
+ sizeof (struct GNUNET_CADET_AxHeader) + esize,
0,
&ax->NHKr,
&msg_hmac);
t_h_decrypt (t,
src,
&plaintext_header);
- Np = ntohl (plaintext_header.Ns);
- PNp = ntohl (plaintext_header.PNs);
- DHRp = &plaintext_header.DHRs;
+ Np = ntohl (plaintext_header.ax_header.Ns);
+ PNp = ntohl (plaintext_header.ax_header.PNs);
+ DHRp = &plaintext_header.ax_header.DHRs;
store_ax_keys (t,
&HK,
PNp);
t_h_decrypt (t,
src,
&plaintext_header);
- Np = ntohl (plaintext_header.Ns);
- PNp = ntohl (plaintext_header.PNs);
+ Np = ntohl (plaintext_header.ax_header.Ns);
+ PNp = ntohl (plaintext_header.ax_header.PNs);
}
if ( (Np != ax->Nr) &&
(GNUNET_OK != store_ax_keys (t,
}
+/**
+ * We lost a connection, remove it from our list and clean up
+ * the connection object itself.
+ *
+ * @param ct binding of connection to tunnel of the connection that was lost.
+ */
+void
+GCT_connection_lost (struct CadetTConnection *ct)
+{
+ struct CadetTunnel *t = ct->t;
+
+ GNUNET_CONTAINER_DLL_remove (t->connection_head,
+ t->connection_tail,
+ ct);
+ GNUNET_free (ct);
+}
+
+
/**
* This tunnel is no longer used, destroy it.
*
GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (t->channels));
while (NULL != (ct = t->connection_head))
{
+ struct CadetConnection *cc;
+
GNUNET_assert (ct->t == t);
- GNUNET_CONTAINER_DLL_remove (t->connection_head,
- t->connection_tail,
- ct);
- GCC_destroy (ct->cc);
- GNUNET_free (ct);
+ cc = ct->cc;
+ GCT_connection_lost (ct);
+ GCC_destroy_without_tunnel (cc);
}
while (NULL != (tq = t->tq_head))
{
/**
- * NOT IMPLEMENTED.
+ * We got a keepalive. Track in statistics.
*
* @param cls the `struct CadetTunnel` for which we decrypted the message
* @param msg the message we received on the tunnel
{
struct CadetTunnel *t = cls;
- GNUNET_break (0); // FIXME
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Received KEEPALIVE on tunnel %s\n",
+ GCT_2s (t));
+ GNUNET_STATISTICS_update (stats,
+ "# keepalives received",
+ 1,
+ GNUNET_NO);
}
* @param t a tunnel
* @param cid connection identifer to use for the connection
* @param path path to use for the connection
+ * @return #GNUNET_OK on success,
+ * #GNUNET_SYSERR on failure (duplicate connection)
*/
-void
+int
GCT_add_inbound_connection (struct CadetTunnel *t,
const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
struct CadetPeerPath *path)
cid,
&connection_ready_cb,
ct);
+ if (NULL == ct->cc)
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Tunnel %s refused inbound connection %s (duplicate)\n",
+ GCT_2s (t),
+ GCC_2s (ct->cc));
+ GNUNET_free (ct);
+ return GNUNET_SYSERR;
+ }
/* FIXME: schedule job to kill connection (and path?) if it takes
too long to get ready! (And track performance data on how long
other connections took with the tunnel!)
"Tunnel %s has new connection %s\n",
GCT_2s (t),
GCC_2s (ct->cc));
+ return GNUNET_OK;
}
&ax_msg[1],
message,
payload_size);
- ax_msg->Ns = htonl (t->ax.Ns++);
- ax_msg->PNs = htonl (t->ax.PNs);
+ ax_msg->ax_header.Ns = htonl (t->ax.Ns++);
+ ax_msg->ax_header.PNs = htonl (t->ax.PNs);
GNUNET_CRYPTO_ecdhe_key_get_public (t->ax.DHRs,
- &ax_msg->DHRs);
+ &ax_msg->ax_header.DHRs);
t_h_encrypt (t,
ax_msg);
- t_hmac (&ax_msg->Ns,
- AX_HEADER_SIZE + payload_size,
+ t_hmac (&ax_msg->ax_header,
+ sizeof (struct GNUNET_CADET_AxHeader) + payload_size,
0,
&t->ax.HKs,
&ax_msg->hmac);