Added SilcIDListData structure and added it to ClientEntry and
authorPekka Riikonen <priikone@silcnet.org>
Tue, 7 Nov 2000 20:55:41 +0000 (20:55 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Tue, 7 Nov 2000 20:55:41 +0000 (20:55 +0000)
ServerEntry so that they can be explicitly casted to the
SilcIDListData without first figuring out the type of the
entry (as it is usually an opaque pointer).

Made basic version router to router connections working. Also
defined better retry connection timeouts.

apps/silcd/command.c
apps/silcd/command_reply.c
apps/silcd/idlist.c
apps/silcd/idlist.h
apps/silcd/protocol.c
apps/silcd/server.c
apps/silcd/server.h
apps/silcd/serverconfig.c
apps/silcd/serverconfig.h
apps/silcd/testi2.conf

index 04901d7ef486390d0908c710ff24453a42355e78..4c4c67be5329a9f6663c49577bc27dfaf15315b8 100644 (file)
@@ -86,25 +86,9 @@ static int silc_server_is_registered(SilcServer server,
                                     SilcServerCommandContext cmd,
                                     SilcCommand command)
 {
-  switch(sock->type) {
-  case SILC_SOCKET_TYPE_CLIENT:
-    {
-      SilcClientEntry client = (SilcClientEntry)sock->user_data;
-      if (client->registered)
-       return TRUE;
-      break;
-    }
-  case SILC_SOCKET_TYPE_SERVER:
-  case SILC_SOCKET_TYPE_ROUTER:
-    {
-      SilcServerEntry serv = (SilcServerEntry)sock->user_data;
-      if (serv->registered)
-       return TRUE;
-      break;
-    }
-  default:
-    break;
-  }
+  SilcIDListData idata = (SilcIDListData)sock->user_data;
+  if (idata->registered)
+    return TRUE;
 
   silc_server_command_send_status_reply(cmd, command,
                                        SILC_STATUS_ERR_NOT_REGISTERED);
@@ -122,6 +106,9 @@ void silc_server_command_process(SilcServer server,
   SilcServerCommand *cmd;
 
 #if 0
+  /* XXX allow commands in but do not execute them more than once per
+     two seconds. */
+
   /* Check whether it is allowed for this connection to execute any
      command. */
   if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
@@ -449,7 +436,7 @@ SILC_SERVER_CMD_FUNC(whois)
       len = hsock->hostname ? strlen(hsock->hostname) : strlen(hsock->ip);
       strncat(uh, hsock->hostname ? hsock->hostname : hsock->ip, len);
       
-      SILC_PUT32_MSB((time(NULL) - entry->last_receive), idle);
+      SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
       
       /* XXX */
       if (entry->userinfo)
index 4ec3a8c37629d2d4a2a34d30b1efcfff8dafa10f..48e906cdeb2a6a1843646065104a96d974e86416 100644 (file)
@@ -166,8 +166,7 @@ SILC_SERVER_CMD_REPLY_FUNC(identify)
        ever gets here it means they don't have this client's information
        in their cache. */
     silc_idlist_add_client(server->global_list, strdup(nickname),
-                          username, NULL, client_id, NULL, NULL, NULL,
-                          NULL, NULL, NULL, NULL);
+                          username, NULL, client_id, NULL, NULL);
   }
 
   if (status == SILC_STATUS_LIST_START) {
index 0699c680a959c9fadf6da166f6edcff262eae1fc..0b770081d0b05168998712424f11253305783ac0 100644 (file)
 #include "serverincludes.h"
 #include "idlist.h"
 
+/******************************************************************************
+
+                             Common functions
+
+******************************************************************************/
+
+/* This function is used to add keys and stuff to common ID entry data
+   structure. */
+
+void silc_idlist_add_data(void *entry, SilcIDListData idata)
+{
+  SilcIDListData data = (SilcIDListData)entry;
+  data->send_key = idata->send_key;
+  data->receive_key = idata->receive_key;
+  data->hmac = idata->hmac;
+  data->hmac_key = idata->hmac_key;
+  data->hmac_key_len = idata->hmac_key_len;
+  data->pkcs = idata->pkcs;
+  data->public_key = idata->public_key;
+  data->last_receive = idata->last_receive;
+  data->last_sent = idata->last_sent;
+  data->registered = idata->registered;
+}
+
+/* Free's all data in the common ID entry data structure. */
+
+void silc_idlist_del_data(void *entry)
+{
+  SilcIDListData idata = (SilcIDListData)entry;
+  if (idata->send_key)
+    silc_cipher_free(idata->send_key);
+  if (idata->receive_key)
+    silc_cipher_free(idata->receive_key);
+  if (idata->hmac)
+    silc_hmac_free(idata->hmac);
+  if (idata->hmac_key) {
+    memset(idata->hmac_key, 0, idata->hmac_key_len);
+    silc_free(idata->hmac_key);
+  }
+  if (idata->pkcs)
+    silc_pkcs_free(idata->pkcs);
+  if (idata->public_key)
+    silc_pkcs_public_key_free(idata->public_key);
+}
+
 /******************************************************************************
 
                           Server entry functions
@@ -37,9 +82,7 @@ SilcServerEntry
 silc_idlist_add_server(SilcIDList id_list, 
                       char *server_name, int server_type,
                       SilcServerID *id, SilcServerEntry router,
-                      SilcCipher send_key, SilcCipher receive_key,
-                      SilcPKCS pkcs, SilcHmac hmac, 
-                      SilcPublicKey public_key, void *connection)
+                      void *connection)
 {
   SilcServerEntry server;
 
@@ -50,11 +93,6 @@ silc_idlist_add_server(SilcIDList id_list,
   server->server_type = server_type;
   server->id = id;
   server->router = router;
-  server->send_key = send_key;
-  server->receive_key = receive_key;
-  server->pkcs = pkcs;
-  server->hmac = hmac;
-  server->public_key = public_key;
   server->connection = connection;
 
   if (!silc_idcache_add(id_list->servers, server->server_name, SILC_ID_SERVER,
@@ -127,10 +165,7 @@ silc_idlist_replace_server_id(SilcIDList id_list, SilcServerID *old_id,
 SilcClientEntry
 silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username,
                       char *userinfo, SilcClientID *id, 
-                      SilcServerEntry router,
-                      SilcCipher send_key, SilcCipher receive_key,
-                      SilcPKCS pkcs, SilcHmac hmac, 
-                      SilcPublicKey public_key, void *connection)
+                      SilcServerEntry router, void *connection)
 {
   SilcClientEntry client;
 
@@ -142,11 +177,6 @@ silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username,
   client->userinfo = userinfo;
   client->id = id;
   client->router = router;
-  client->send_key = send_key;
-  client->receive_key = receive_key;
-  client->pkcs = pkcs;
-  client->hmac = hmac;
-  client->public_key = public_key;
   client->connection = connection;
   silc_list_init(client->channels, struct SilcChannelClientEntryStruct, 
                 client_list);
@@ -161,7 +191,7 @@ silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username,
 }
 
 /* Free client entry. This free's everything and removes the entry
-   from ID cache. */
+   from ID cache. Call silc_idlist_del_data before calling this one. */
 
 void silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry)
 {
@@ -180,16 +210,6 @@ void silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry)
       silc_free(entry->userinfo);
     if (entry->id)
       silc_free(entry->id);
-    if (entry->send_key)
-      silc_cipher_free(entry->send_key);
-    if (entry->receive_key)
-      silc_cipher_free(entry->receive_key);
-    if (entry->pkcs)
-      silc_pkcs_free(entry->pkcs);
-    if (entry->public_key)
-      silc_pkcs_public_key_free(entry->public_key);
-    if (entry->hmac)
-      silc_hmac_free(entry->hmac);
   }
 }
 
index 52d3307e7bb9eb4e887cee156701b93644f20811..47448b95465c78db971c3bc132743c4523bb9b57 100644 (file)
@@ -26,6 +26,41 @@ typedef struct SilcServerEntryStruct *SilcServerEntry;
 typedef struct SilcClientEntryStruct *SilcClientEntry;
 typedef struct SilcChannelEntryStruct *SilcChannelEntry;
 
+/*
+   Generic ID list data structure.
+
+   This structure is included in all ID list entries and it includes data
+   pointers that are common to all ID entries.  This structure is always
+   defined to the first field in the ID entries and is used to explicitly
+   cast to this type without first explicitly casting to correct ID entry
+   type.  Hence, the ID list entry is casted to this type to get this data
+   from the ID entry (which is usually opaque pointer).
+
+   Note that some of the fields may be NULL.
+
+*/
+typedef struct {
+  /* Send and receive symmetric keys */
+  SilcCipher send_key;
+  SilcCipher receive_key;
+
+  /* HMAC and raw key data */
+  SilcHmac hmac;
+  unsigned char *hmac_key;
+  unsigned int hmac_key_len;
+
+  /* PKCS and public key */
+  SilcPKCS pkcs;
+  SilcPublicKey public_key;
+
+  /* Time when last received or sent data */
+  long last_receive;
+  long last_sent;
+
+  /* Boolean value whether connection is registered */
+  int registered;
+} *SilcIDListData, SilcIDListDataStruct;
+
 /* 
    SILC Server entry object.
 
@@ -45,6 +80,10 @@ typedef struct SilcChannelEntryStruct *SilcChannelEntry;
 
    Following short description of the fields:
 
+   SilcIDListDataStruct data
+
+       Generic data structure to hold data common to all ID entries.
+
    char *server_name
 
        Logical name of the server. There is no limit of the length of the
@@ -61,10 +100,6 @@ typedef struct SilcChannelEntryStruct *SilcChannelEntry;
        the server SILC will ever need. These are also the informations
        that is broadcasted between servers and routers in the SILC network.
 
-   long last_receive
-
-       Time when data was received from the server last time.
-
    SilcServerEntry router
 
        This is a pointer back to the server list. This is the router server 
@@ -85,26 +120,16 @@ typedef struct SilcChannelEntryStruct *SilcChannelEntry;
    
 */
 struct SilcServerEntryStruct {
+  /* Generic data structure. DO NOT add anything before this! */
+  SilcIDListDataStruct data;
+
   char *server_name;
   int server_type;
   SilcServerID *id;
-  long last_receive;
-
-  /* TRUE when server is registered to server */
-  int registered;
 
   /* Pointer to the router */
   SilcServerEntry router;
 
-  /* Keys */
-  SilcCipher send_key;
-  SilcCipher receive_key;
-  SilcPKCS pkcs;
-  SilcPublicKey public_key;
-  SilcHmac hmac;
-  unsigned char *hmac_key;
-  unsigned int hmac_key_len;
-
   /* Connection data */
   void *connection;
 };
@@ -165,6 +190,10 @@ typedef struct SilcChannelClientEntryStruct {
 
    Following short description of the fields:
 
+   SilcIDListDataStruct data
+
+       Generic data structure to hold data common to all ID entries.
+
    char username
 
        Client's (meaning user's) real name. This is defined in following 
@@ -209,23 +238,12 @@ typedef struct SilcChannelClientEntryStruct {
        Client's mode.  Client maybe for example server operator or
        router operator (SILC operator).
 
-   long last_receive
-
-       Time of last time data was received from the client. This is
-       result of normal time().
-
    long last_command
 
        Time of last time client executed command. We are strict and will
        not allow any command to be exeucted more than once in about
        2 seconds. This is result of normal time().
 
-   int registered
-
-       Boolean value to indicate whether this client has registered itself
-       to the server. After KE and authentication protocols has been
-       successfully completed will client become registered.
-
    SilcServerEntry router
 
        This is a pointer to the server list. This is the router server whose 
@@ -254,32 +272,23 @@ typedef struct SilcChannelClientEntryStruct {
 
 */
 struct SilcClientEntryStruct {
+  /* Generic data structure. DO NOT add anything before this! */
+  SilcIDListDataStruct data;
+
   char *nickname;
   char *username;
   char *userinfo;
   SilcClientID *id;
   int mode;
 
-  /* Time of last accesses of the client */
-  long last_receive;
   long last_command;
 
-  /* TRUE when client is registered to server */
-  int registered;
-
   /* Pointer to the router */
   SilcServerEntry router;
 
   /* List of channels client has joined to */
   SilcList channels;
 
-  /* Keys */
-  SilcCipher send_key;
-  SilcCipher receive_key;
-  SilcPKCS pkcs;
-  SilcHmac hmac;
-  SilcPublicKey public_key;
-
   /* Connection data */
   void *connection;
 };
@@ -441,26 +450,18 @@ typedef struct SilcIDListStruct {
 
 */
 typedef struct {
-  SilcCipher send_key;
-  SilcCipher receive_key;
-  SilcPKCS pkcs;
-  SilcPublicKey public_key;
-
-  SilcHmac hmac;
-  unsigned char *hmac_key;
-  unsigned int hmac_key_len;
-
-  /* SilcComp comp */
+  /* Generic data structure. DO NOT add anything before this! */
+  SilcIDListDataStruct data;
 } *SilcUnknownEntry;
 
 /* Prototypes */
+void silc_idlist_add_data(void *entry, SilcIDListData idata);
+void silc_idlist_del_data(void *entry);
 SilcServerEntry 
 silc_idlist_add_server(SilcIDList id_list, 
                       char *server_name, int server_type,
                       SilcServerID *id, SilcServerEntry router,
-                      SilcCipher send_key, SilcCipher receive_key,
-                      SilcPKCS pkcs, SilcHmac hmac, 
-                      SilcPublicKey public_key, void *connection);
+                      void *connection);
 SilcServerEntry
 silc_idlist_find_server_by_id(SilcIDList id_list, SilcServerID *id);
 SilcServerEntry
@@ -469,10 +470,7 @@ silc_idlist_replace_server_id(SilcIDList id_list, SilcServerID *old_id,
 SilcClientEntry
 silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username,
                       char *userinfo, SilcClientID *id, 
-                      SilcServerEntry router,
-                      SilcCipher send_key, SilcCipher receive_key,
-                      SilcPKCS pkcs, SilcHmac hmac, 
-                      SilcPublicKey public_key, void *connection);
+                      SilcServerEntry router, void *connection);
 void silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry);
 SilcClientEntry *
 silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname,
index b8cb0090fd7fc50774b5da577f0319edbc5a3252..6bfef69e912a7bcb1aa3c2acea418784385cff22 100644 (file)
@@ -63,35 +63,37 @@ static void silc_server_protocol_ke_set_keys(SilcSKE ske,
                                             int is_responder)
 {
   SilcUnknownEntry conn_data;
+  SilcIDListData idata;
   SilcHash nhash;
 
   SILC_LOG_DEBUG(("Setting new key into use"));
 
   conn_data = silc_calloc(1, sizeof(*conn_data));
+  idata = (SilcIDListData)conn_data;
 
   /* Allocate cipher to be used in the communication */
-  silc_cipher_alloc(cipher->cipher->name, &conn_data->send_key);
-  silc_cipher_alloc(cipher->cipher->name, &conn_data->receive_key);
+  silc_cipher_alloc(cipher->cipher->name, &idata->send_key);
+  silc_cipher_alloc(cipher->cipher->name, &idata->receive_key);
   
   if (is_responder == TRUE) {
-    conn_data->send_key->cipher->set_key(conn_data->send_key->context, 
-                                        keymat->receive_enc_key, 
-                                        keymat->enc_key_len);
-    conn_data->send_key->set_iv(conn_data->send_key, keymat->receive_iv);
-    conn_data->receive_key->cipher->set_key(conn_data->receive_key->context, 
-                                           keymat->send_enc_key, 
-                                           keymat->enc_key_len);
-    conn_data->receive_key->set_iv(conn_data->receive_key, keymat->send_iv);
+    idata->send_key->cipher->set_key(idata->send_key->context, 
+                                    keymat->receive_enc_key, 
+                                    keymat->enc_key_len);
+    idata->send_key->set_iv(idata->send_key, keymat->receive_iv);
+    idata->receive_key->cipher->set_key(idata->receive_key->context, 
+                                       keymat->send_enc_key, 
+                                       keymat->enc_key_len);
+    idata->receive_key->set_iv(idata->receive_key, keymat->send_iv);
     
   } else {
-    conn_data->send_key->cipher->set_key(conn_data->send_key->context, 
-                                        keymat->send_enc_key, 
-                                        keymat->enc_key_len);
-    conn_data->send_key->set_iv(conn_data->send_key, keymat->send_iv);
-    conn_data->receive_key->cipher->set_key(conn_data->receive_key->context, 
-                                           keymat->receive_enc_key, 
-                                           keymat->enc_key_len);
-    conn_data->receive_key->set_iv(conn_data->receive_key, keymat->receive_iv);
+    idata->send_key->cipher->set_key(idata->send_key->context, 
+                                    keymat->send_enc_key, 
+                                    keymat->enc_key_len);
+    idata->send_key->set_iv(idata->send_key, keymat->send_iv);
+    idata->receive_key->cipher->set_key(idata->receive_key->context, 
+                                       keymat->receive_enc_key, 
+                                       keymat->enc_key_len);
+    idata->receive_key->set_iv(idata->receive_key, keymat->receive_iv);
   }
 
   /* Allocate PKCS to be used */
@@ -99,16 +101,16 @@ static void silc_server_protocol_ke_set_keys(SilcSKE ske,
   /* XXX Do we ever need to allocate PKCS for the connection??
      If yes, we need to change KE protocol to get the initiators
      public key. */
-  silc_pkcs_alloc(pkcs->pkcs->name, &conn_data->pkcs);
-  conn_data->public_key = silc_pkcs_public_key_alloc(XXX);
-  silc_pkcs_set_public_key(conn_data->pkcs, ske->ke2_payload->pk_data, 
+  silc_pkcs_alloc(pkcs->pkcs->name, &idata->pkcs);
+  idata->public_key = silc_pkcs_public_key_alloc(XXX);
+  silc_pkcs_set_public_key(idata->pkcs, ske->ke2_payload->pk_data, 
                           ske->ke2_payload->pk_len);
 #endif
 
   /* Save HMAC key to be used in the communication. */
   silc_hash_alloc(hash->hash->name, &nhash);
-  silc_hmac_alloc(nhash, &conn_data->hmac);
-  silc_hmac_set_key(conn_data->hmac, keymat->hmac_key, keymat->hmac_key_len);
+  silc_hmac_alloc(nhash, &idata->hmac);
+  silc_hmac_set_key(idata->hmac, keymat->hmac_key, keymat->hmac_key_len);
 
   sock->user_data = (void *)conn_data;
 }
index d95352867312e189c670e2f3b790443bcf48d740..249991f9438973d82863dc311833d009770ae9f6 100644 (file)
@@ -54,7 +54,7 @@ int silc_server_alloc(SilcServer *new_server)
 
   server = silc_calloc(1, sizeof(*server));
   server->server_type = SILC_SERVER;
-  server->standalone = FALSE;
+  server->standalone = TRUE;
   server->local_list = silc_calloc(1, sizeof(*server->local_list));
   server->global_list = silc_calloc(1, sizeof(*server->global_list));
 #ifdef SILC_SIM
@@ -257,9 +257,7 @@ int silc_server_init(SilcServer server)
     id_entry = 
       silc_idlist_add_server(server->local_list,
                             server->config->server_info->server_name,
-                            server->server_type, server->id, NULL,
-                            server->send_key, server->receive_key,
-                            NULL, NULL, NULL, NULL);
+                            server->server_type, server->id, NULL, NULL);
     if (!id_entry) {
       SILC_LOG_ERROR(("Could not add ourselves to cache"));
       goto err0;
@@ -309,13 +307,20 @@ int silc_server_init(SilcServer server)
      timeout. It expires as soon as the caller calls silc_server_run. This
      task performs authentication protocol and key exchange with our
      primary router. */
-  if (silc_task_register(server->timeout_queue, sock[0], 
-                        silc_server_connect_to_router,
-                        (void *)server, 0, 1,
-                        SILC_TASK_TIMEOUT,
-                        SILC_TASK_PRI_NORMAL) == NULL) {
-    goto err2;
-  }
+  silc_task_register(server->timeout_queue, sock[0], 
+                    silc_server_connect_to_router,
+                    (void *)server, 0, 1,
+                    SILC_TASK_TIMEOUT,
+                    SILC_TASK_PRI_NORMAL);
+
+  /* Add listener task to the queue. This task receives new connections to the 
+     server. This task remains on the queue until the end of the program. */
+  silc_task_register(server->io_queue, sock[0],
+                    silc_server_accept_new_connection,
+                    (void *)server, 0, 0, 
+                    SILC_TASK_FD,
+                    SILC_TASK_PRI_NORMAL);
+  server->listenning = TRUE;
 
   /* If server connections has been configured then we must be router as
      normal server cannot have server connections, only router connections. */
@@ -327,7 +332,6 @@ int silc_server_init(SilcServer server)
   /* We are done here, return succesfully */
   return TRUE;
 
- err2:
   silc_task_queue_free(server->timeout_queue);
  err1:
   silc_task_queue_free(server->io_queue);
@@ -527,16 +531,22 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router)
     ptr = server->config->routers;
     while (ptr) {
 
-      /* Allocate connection object for hold connection specific stuff. */
-      sconn = silc_calloc(1, sizeof(*sconn));
-      sconn->server = server;
-      sconn->remote_host = ptr->host;
-      sconn->remote_port = ptr->port;
-
-      silc_task_register(server->timeout_queue, fd, 
-                        silc_server_connect_router,
-                        (void *)sconn, 0, 1, SILC_TASK_TIMEOUT, 
-                        SILC_TASK_PRI_NORMAL);
+      SILC_LOG_DEBUG(("Router connection [%s] %s:%d",
+                     ptr->initiator ? "Initiator" : "Responder",
+                     ptr->host, ptr->port));
+
+      if (ptr->initiator) {
+       /* Allocate connection object for hold connection specific stuff. */
+       sconn = silc_calloc(1, sizeof(*sconn));
+       sconn->server = server;
+       sconn->remote_host = ptr->host;
+       sconn->remote_port = ptr->port;
+
+       silc_task_register(server->timeout_queue, fd, 
+                          silc_server_connect_router,
+                          (void *)sconn, 0, 1, SILC_TASK_TIMEOUT, 
+                          SILC_TASK_PRI_NORMAL);
+      }
 
       if (!ptr->next)
        return;
@@ -550,14 +560,6 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router)
   /* There wasn't a configured router, we will continue but we don't
      have a connection to outside world.  We will be standalone server. */
   server->standalone = TRUE;
-
-  /* Add a task to the queue. This task receives new connections to the 
-     server. This task remains on the queue until the end of the program. */
-  silc_task_register(server->io_queue, fd, 
-                    silc_server_accept_new_connection,
-                    (void *)server, 0, 0, 
-                    SILC_TASK_FD,
-                    SILC_TASK_PRI_NORMAL);
 }
 
 /* Second part of connecting to router(s). Key exchange protocol has been
@@ -667,7 +669,6 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final)
   SilcServerConnection sconn = (SilcServerConnection)ctx->context;
   SilcSocketConnection sock = ctx->sock;
   SilcServerEntry id_entry;
-  SilcUnknownEntry conn_data;
   SilcBuffer packet;
   unsigned char *id_string;
 
@@ -675,18 +676,11 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final)
 
   if (protocol->state == SILC_PROTOCOL_STATE_ERROR) {
     /* Error occured during protocol */
-    silc_protocol_free(protocol);
-    if (ctx->packet)
-      silc_buffer_free(ctx->packet);
-    if (ctx->ske)
-      silc_ske_free(ctx->ske);
     if (ctx->dest_id)
       silc_free(ctx->dest_id);
-    silc_free(ctx);
-    sock->protocol = NULL;
     silc_server_disconnect_remote(server, sock, "Server closed connection: "
                                  "Authentication failed");
-    return;
+    goto out;
   }
 
   /* Add a task to the queue. This task receives new connections to the 
@@ -724,23 +718,25 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final)
 
   /* Add the connected router to local server list */
   server->standalone = FALSE;
-  conn_data = (SilcUnknownEntry)sock->user_data;
-  id_entry =
-    silc_idlist_add_server(server->local_list, 
-                          sock->hostname ? sock->hostname : sock->ip,
-                          SILC_ROUTER, ctx->dest_id, NULL,
-                          conn_data->send_key, conn_data->receive_key,
-                          conn_data->pkcs, conn_data->hmac, NULL, sock);
-  if (id_entry) {
-    id_entry->hmac_key = conn_data->hmac_key;
-    id_entry->hmac_key_len = conn_data->hmac_key_len;
-    sock->user_data = (void *)id_entry;
-    sock->type = SILC_SOCKET_TYPE_ROUTER;
-    server->id_entry->router = id_entry;
+  id_entry = silc_idlist_add_server(server->local_list, 
+                                   sock->hostname ? sock->hostname : sock->ip,
+                                   SILC_ROUTER, ctx->dest_id, NULL, sock);
+  if (!id_entry) {
+    if (ctx->dest_id)
+      silc_free(ctx->dest_id);
+    silc_server_disconnect_remote(server, sock, "Server closed connection: "
+                                 "Authentication failed");
+    goto out;
   }
-    
-  /* Free the temporary connection data context from key exchange */
-  silc_free(conn_data);
+
+  silc_idlist_add_data(id_entry, (SilcIDListData)sock->user_data);
+  silc_free(sock->user_data);
+  sock->user_data = (void *)id_entry;
+  sock->type = SILC_SOCKET_TYPE_ROUTER;
+  server->id_entry->router = id_entry;
+
+ out:
+  /* Free the temporary connection data context */
   if (sconn)
     silc_free(sconn);
 
@@ -923,6 +919,7 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
     (SilcServerConnAuthInternalContext *)protocol->context;
   SilcServer server = (SilcServer)ctx->server;
   SilcSocketConnection sock = ctx->sock;
+  void *id_entry = NULL;
 
   SILC_LOG_DEBUG(("Start"));
 
@@ -948,7 +945,6 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
   case SILC_SOCKET_TYPE_CLIENT:
     {
       SilcClientEntry client;
-      SilcUnknownEntry conn_data = (SilcUnknownEntry)sock->user_data;
 
       SILC_LOG_DEBUG(("Remote host is client"));
       SILC_LOG_INFO(("Connection from %s (%s) is client", sock->hostname,
@@ -957,29 +953,21 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
       /* Add the client to the client ID cache. The nickname and Client ID
         and other information is created after we have received NEW_CLIENT
         packet from client. */
-      client = 
-       silc_idlist_add_client(server->local_list, NULL, NULL, NULL, NULL,
-                              NULL, conn_data->send_key, 
-                              conn_data->receive_key, conn_data->pkcs,
-                              conn_data->hmac, NULL, sock);
+      client = silc_idlist_add_client(server->local_list, 
+                                     NULL, NULL, NULL, NULL, NULL, sock);
       if (!client) {
        SILC_LOG_ERROR(("Could not add new client to cache"));
-       silc_free(conn_data);
+       silc_free(sock->user_data);
        break;
       }
 
-      /* Free the temporary connection data context from key exchange */
-      silc_free(conn_data);
-
-      /* Add to sockets internal pointer for fast referencing */
-      sock->user_data = (void *)client;
+      id_entry = (void *)client;
       break;
     }
   case SILC_SOCKET_TYPE_SERVER:
   case SILC_SOCKET_TYPE_ROUTER:
     {
       SilcServerEntry new_server;
-      SilcUnknownEntry conn_data = (SilcUnknownEntry)sock->user_data;
 
       SILC_LOG_DEBUG(("Remote host is %s", 
                      sock->type == SILC_SOCKET_TYPE_SERVER ? 
@@ -994,25 +982,15 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
       new_server = 
        silc_idlist_add_server(server->local_list, NULL,
                               sock->type == SILC_SOCKET_TYPE_SERVER ?
-                              SILC_SERVER : SILC_ROUTER, NULL, NULL,
-                              conn_data->send_key, conn_data->receive_key,
-                              conn_data->pkcs, conn_data->hmac, NULL, sock);
+                              SILC_SERVER : SILC_ROUTER, NULL, NULL, sock);
       if (!new_server) {
        SILC_LOG_ERROR(("Could not add new server to cache"));
-       silc_free(conn_data);
+       silc_free(sock->user_data);
        break;
       }
-      
-      new_server->registered = TRUE;
-      new_server->hmac_key = conn_data->hmac_key;
-      new_server->hmac_key_len = conn_data->hmac_key_len;
-      
-      /* Free the temporary connection data context from protocols */
-      silc_free(conn_data);
-
-      /* Add to sockets internal pointer for fast referencing */
-      sock->user_data = (void *)new_server;
 
+      id_entry = (void *)new_server;
+      
       /* There is connection to other server now, if it is router then
         we will have connection to outside world.  If we are router but
         normal server connected to us then we will remain standalone,
@@ -1020,6 +998,8 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
       if (server->standalone && sock->type == SILC_SOCKET_TYPE_ROUTER) {
        SILC_LOG_DEBUG(("We are not standalone server anymore"));
        server->standalone = FALSE;
+       if (!server->id_entry->router)
+         server->id_entry->router = id_entry;
       }
       break;
     }
@@ -1027,6 +1007,14 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
     break;
   }
 
+  /* Add the common data structure to the ID entry. */
+  if (id_entry)
+    silc_idlist_add_data(id_entry, (SilcIDListData)sock->user_data);
+      
+  /* Add to sockets internal pointer for fast referencing */
+  silc_free(sock->user_data);
+  sock->user_data = id_entry;
+
   /* Connection has been fully established now. Everything is ok. */
   SILC_LOG_DEBUG(("New connection authenticated"));
 
@@ -1085,6 +1073,7 @@ SILC_TASK_CALLBACK(silc_server_packet_process)
 {
   SilcServer server = (SilcServer)context;
   SilcSocketConnection sock = server->sockets[fd];
+  SilcIDListData idata;
   SilcCipher cipher = NULL;
   SilcHmac hmac = NULL;
   int ret;
@@ -1096,8 +1085,7 @@ SILC_TASK_CALLBACK(silc_server_packet_process)
     SILC_LOG_DEBUG(("Writing data to connection"));
 
     if (sock->outbuf->data - sock->outbuf->head)
-      silc_buffer_push(sock->outbuf, 
-                      sock->outbuf->data - sock->outbuf->head);
+      silc_buffer_push(sock->outbuf, sock->outbuf->data - sock->outbuf->head);
 
     ret = silc_server_packet_send_real(server, sock, TRUE);
 
@@ -1118,87 +1106,53 @@ SILC_TASK_CALLBACK(silc_server_packet_process)
   }
 
   /* Packet receiving */
-  if (type == SILC_TASK_READ) {
-    SILC_LOG_DEBUG(("Reading data from connection"));
+  SILC_LOG_DEBUG(("Reading data from connection"));
 
-    /* Read some data from connection */
-    ret = silc_packet_receive(sock);
-    if (ret < 0)
-      return;
+  /* Read some data from connection */
+  ret = silc_packet_receive(sock);
+  if (ret < 0)
+    return;
     
-    /* EOF */
-    if (ret == 0) {
-      SILC_LOG_DEBUG(("Read EOF"));
-      
-      /* If connection is disconnecting already we will finally
-        close the connection */
-      if (SILC_IS_DISCONNECTING(sock)) {
-       if (sock->user_data)
-         silc_server_free_sock_user_data(server, sock);
-       silc_server_close_connection(server, sock);
-       return;
-      }
+  /* EOF */
+  if (ret == 0) {
+    SILC_LOG_DEBUG(("Read EOF"));
       
-      SILC_LOG_DEBUG(("Premature EOF from connection %d", sock->sock));
-
+    /* If connection is disconnecting already we will finally
+       close the connection */
+    if (SILC_IS_DISCONNECTING(sock)) {
       if (sock->user_data)
-         silc_server_free_sock_user_data(server, sock);
+       silc_server_free_sock_user_data(server, sock);
       silc_server_close_connection(server, sock);
       return;
     }
+      
+    SILC_LOG_DEBUG(("Premature EOF from connection %d", sock->sock));
 
-    /* If connection is disconnecting or disconnected we will ignore
-       what we read. */
-    if (SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock)) {
-      SILC_LOG_DEBUG(("Ignoring read data from invalid connection"));
-      return;
-    }
-
-    switch (sock->type) {
-    case SILC_SOCKET_TYPE_CLIENT:
-      {
-       SilcClientEntry clnt = (SilcClientEntry)sock->user_data;
-       if (!clnt)
-         break;
-
-       clnt->last_receive = time(NULL);
-
-       cipher = clnt->receive_key;
-       hmac = clnt->hmac;
-       break;
-      }
-    case SILC_SOCKET_TYPE_SERVER:
-    case SILC_SOCKET_TYPE_ROUTER:
-      {
-       SilcServerEntry srvr = (SilcServerEntry)sock->user_data;
-       if (!srvr)
-         break;
-
-       srvr->last_receive = time(NULL);
+    if (sock->user_data)
+      silc_server_free_sock_user_data(server, sock);
+    silc_server_close_connection(server, sock);
+    return;
+  }
 
-       cipher = srvr->receive_key;
-       hmac = srvr->hmac;
-       break;
-      }
-    case SILC_SOCKET_TYPE_UNKNOWN:
-      {
-       SilcUnknownEntry conn_data = (SilcUnknownEntry)sock->user_data;
-       if (!conn_data)
-         break;
+  /* If connection is disconnecting or disconnected we will ignore
+     what we read. */
+  if (SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock)) {
+    SILC_LOG_DEBUG(("Ignoring read data from invalid connection"));
+    return;
+  }
 
-       cipher = conn_data->receive_key;
-       hmac = conn_data->hmac;
-       break;
-      }
-    default:
-      return;
-    }
-    /* Process the packet. This will call the parser that will then
-       decrypt and parse the packet. */
-    silc_packet_receive_process(sock, cipher, hmac,
-                               silc_server_packet_parse, server);
+  /* Get keys and stuff from ID entry */
+  idata = (SilcIDListData)sock->user_data;
+  if (idata) {
+    idata->last_receive = time(NULL);
+    cipher = idata->receive_key;
+    hmac = idata->hmac;
   }
+  /* Process the packet. This will call the parser that will then
+     decrypt and parse the packet. */
+  silc_packet_receive_process(sock, cipher, hmac, silc_server_packet_parse, 
+                             server);
 }
 
 /* Parses whole packet, received earlier. */
@@ -1584,17 +1538,13 @@ void silc_server_packet_send(SilcServer server,
   /* Get data used in the packet sending, keys and stuff */
   switch(sock->type) {
   case SILC_SOCKET_TYPE_CLIENT:
-    if (((SilcClientEntry)sock->user_data)->id) {
-      dst_id = ((SilcClientEntry)sock->user_data)->id;
-      dst_id_type = SILC_ID_CLIENT;
-    }
+    dst_id = ((SilcClientEntry)sock->user_data)->id;
+    dst_id_type = SILC_ID_CLIENT;
     break;
   case SILC_SOCKET_TYPE_SERVER:
   case SILC_SOCKET_TYPE_ROUTER:
-    if (((SilcServerEntry)sock->user_data)->id) {
-      dst_id = ((SilcServerEntry)sock->user_data)->id;
-      dst_id_type = SILC_ID_SERVER;
-    }
+    dst_id = ((SilcServerEntry)sock->user_data)->id;
+    dst_id_type = SILC_ID_SERVER;
     break;
   default:
     break;
@@ -1622,6 +1572,7 @@ void silc_server_packet_send_dest(SilcServer server,
                                  int force_send)
 {
   SilcPacketContext packetdata;
+  SilcIDListData idata;
   SilcCipher cipher = NULL;
   SilcHmac hmac = NULL;
   unsigned char *dst_id_data = NULL;
@@ -1630,29 +1581,7 @@ void silc_server_packet_send_dest(SilcServer server,
   SILC_LOG_DEBUG(("Sending packet, type %d", type));
 
   /* Get data used in the packet sending, keys and stuff */
-  switch(sock->type) {
-  case SILC_SOCKET_TYPE_CLIENT:
-    if (sock->user_data) {
-      cipher = ((SilcClientEntry)sock->user_data)->send_key;
-      hmac = ((SilcClientEntry)sock->user_data)->hmac;
-    }
-    break;
-  case SILC_SOCKET_TYPE_SERVER:
-  case SILC_SOCKET_TYPE_ROUTER:
-    if (sock->user_data) {
-      cipher = ((SilcServerEntry)sock->user_data)->send_key;
-      hmac = ((SilcServerEntry)sock->user_data)->hmac;
-    }
-    break;
-  default:
-    if (sock->user_data) {
-      /* We don't know what type of connection this is thus it must
-        be in authentication phase. */
-      cipher = ((SilcUnknownEntry)sock->user_data)->send_key;
-      hmac = ((SilcUnknownEntry)sock->user_data)->hmac;
-    }
-    break;
-  }
+  idata = (SilcIDListData)sock->user_data;
 
   if (dst_id) {
     dst_id_data = silc_id_id2str(dst_id, dst_id_type);
@@ -1692,9 +1621,13 @@ void silc_server_packet_send_dest(SilcServer server,
   /* Create the outgoing packet */
   silc_packet_assemble(&packetdata);
 
+  if (idata) {
+    cipher = idata->send_key;
+    hmac = idata->hmac;
+  }
+
   /* Encrypt the packet */
-  if (cipher)
-    silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
+  silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
 
   SILC_LOG_HEXDUMP(("Outgoing packet, len %d", sock->outbuf->len),
                   sock->outbuf->data, sock->outbuf->len);
@@ -1720,31 +1653,14 @@ void silc_server_packet_forward(SilcServer server,
                                unsigned char *data, unsigned int data_len,
                                int force_send)
 {
+  SilcIDListData idata;
   SilcCipher cipher = NULL;
   SilcHmac hmac = NULL;
 
   SILC_LOG_DEBUG(("Forwarding packet"));
 
   /* Get data used in the packet sending, keys and stuff */
-  switch(sock->type) {
-  case SILC_SOCKET_TYPE_CLIENT:
-    if (sock->user_data) {
-      cipher = ((SilcClientEntry )sock->user_data)->send_key;
-      hmac = ((SilcClientEntry )sock->user_data)->hmac;
-    }
-    break;
-  case SILC_SOCKET_TYPE_SERVER:
-  case SILC_SOCKET_TYPE_ROUTER:
-    if (sock->user_data) {
-      cipher = ((SilcServerEntry )sock->user_data)->send_key;
-      hmac = ((SilcServerEntry )sock->user_data)->hmac;
-    }
-    break;
-  default:
-    /* We won't forward to unknown destination - keys must exist with
-       the destination before forwarding. */
-    return;
-  }
+  idata = (SilcIDListData)sock->user_data;
 
   /* Prepare outgoing data buffer for packet sending */
   silc_packet_send_prepare(sock, 0, 0, data_len);
@@ -1757,9 +1673,13 @@ void silc_server_packet_forward(SilcServer server,
   if (data && data_len)
     silc_buffer_put(sock->outbuf, data, data_len);
 
+  if (idata) {
+    cipher = idata->send_key;
+    hmac = idata->hmac;
+  }
+
   /* Encrypt the packet */
-  if (cipher)
-    silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
+  silc_packet_encrypt(cipher, hmac, sock->outbuf, sock->outbuf->len);
 
   SILC_LOG_HEXDUMP(("Forwarded packet, len %d", sock->outbuf->len),
                   sock->outbuf->data, sock->outbuf->len);
@@ -1832,9 +1752,8 @@ void silc_server_packet_send_to_channel(SilcServer server,
   SilcClientEntry client = NULL;
   SilcServerEntry *routed = NULL;
   SilcChannelClientEntry chl;
+  SilcIDListData idata;
   unsigned int routed_count = 0;
-  SilcCipher cipher;
-  SilcHmac hmac;
 
   /* This doesn't send channel message packets */
   if (type == SILC_PACKET_CHANNEL_MESSAGE)
@@ -1865,14 +1784,13 @@ void silc_server_packet_send_to_channel(SilcServer server,
     /* Get data used in packet header encryption, keys and stuff. */
     router = server->id_entry->router;
     sock = (SilcSocketConnection)router->connection;
-    cipher = router->send_key;
-    hmac = router->hmac;
+    idata = (SilcIDListData)router;
     
     SILC_LOG_DEBUG(("Sending channel message to router for routing"));
 
     silc_server_packet_send_to_channel_real(server, sock, &packetdata,
-                                           cipher, hmac, data,
-                                           data_len, FALSE, force_send);
+                                           idata->send_key, idata->hmac, 
+                                           data, data_len, FALSE, force_send);
   }
 
   /* Send the message to clients on the channel's client list. */
@@ -1894,13 +1812,13 @@ void silc_server_packet_send_to_channel(SilcServer server,
 
       /* Get data used in packet header encryption, keys and stuff. */
       sock = (SilcSocketConnection)client->router->connection;
-      cipher = client->router->send_key;
-      hmac = client->router->hmac;
+      idata = (SilcIDListData)client->router;
 
       /* Send the packet */
       silc_server_packet_send_to_channel_real(server, sock, &packetdata,
-                                             cipher, hmac, data,
-                                             data_len, FALSE, force_send);
+                                             idata->send_key, idata->hmac, 
+                                             data, data_len, FALSE, 
+                                             force_send);
 
       /* We want to make sure that the packet is routed to same router
         only once. Mark this route as sent route. */
@@ -1917,13 +1835,13 @@ void silc_server_packet_send_to_channel(SilcServer server,
 
       /* Get data used in packet header encryption, keys and stuff. */
       sock = (SilcSocketConnection)client->connection;
-      cipher = client->send_key;
-      hmac = client->hmac;
-      
+      idata = (SilcIDListData)client;
+
       /* Send the packet */
       silc_server_packet_send_to_channel_real(server, sock, &packetdata,
-                                             cipher, hmac, data,
-                                             data_len, FALSE, force_send);
+                                             idata->send_key, idata->hmac, 
+                                             data, data_len, FALSE, 
+                                             force_send);
     }
   }
 
@@ -1958,8 +1876,7 @@ void silc_server_packet_relay_to_channel(SilcServer server,
   SilcServerEntry *routed = NULL;
   SilcChannelClientEntry chl;
   unsigned int routed_count = 0;
-  SilcCipher cipher;
-  SilcHmac hmac;
+  SilcIDListData idata;
 
   SILC_LOG_DEBUG(("Relaying packet to channel"));
 
@@ -1990,14 +1907,14 @@ void silc_server_packet_relay_to_channel(SilcServer server,
 
       /* Get data used in packet header encryption, keys and stuff. */
       sock = (SilcSocketConnection)router->connection;
-      cipher = router->send_key;
-      hmac = router->hmac;
+      idata = (SilcIDListData)router;
 
       SILC_LOG_DEBUG(("Sending channel message to router for routing"));
 
       silc_server_packet_send_to_channel_real(server, sock, &packetdata,
-                                             cipher, hmac, data,
-                                             data_len, TRUE, force_send);
+                                             idata->send_key, idata->hmac, 
+                                             data, data_len, TRUE, 
+                                             force_send);
     }
   }
 
@@ -2035,13 +1952,13 @@ void silc_server_packet_relay_to_channel(SilcServer server,
        
        /* Get data used in packet header encryption, keys and stuff. */
        sock = (SilcSocketConnection)client->router->connection;
-       cipher = client->router->send_key;
-       hmac = client->router->hmac;
+       idata = (SilcIDListData)client->router;
 
        /* Send the packet */
        silc_server_packet_send_to_channel_real(server, sock, &packetdata,
-                                               cipher, hmac, data,
-                                               data_len, TRUE, force_send);
+                                               idata->send_key, idata->hmac, 
+                                               data, data_len, TRUE, 
+                                               force_send);
        
        /* We want to make sure that the packet is routed to same router
           only once. Mark this route as sent route. */
@@ -2057,16 +1974,16 @@ void silc_server_packet_relay_to_channel(SilcServer server,
 
       /* Get data used in packet header encryption, keys and stuff. */
       sock = (SilcSocketConnection)client->connection;
-      cipher = client->send_key;
-      hmac = client->hmac;
+      idata = (SilcIDListData)client;
 
       SILC_LOG_DEBUG(("Sending packet to client %s", 
                      sock->hostname ? sock->hostname : sock->ip));
 
       /* Send the packet */
       silc_server_packet_send_to_channel_real(server, sock, &packetdata,
-                                             cipher, hmac, data,
-                                             data_len, TRUE, force_send);
+                                             idata->send_key, idata->hmac, 
+                                             data, data_len, TRUE, 
+                                             force_send);
     }
   }
 
@@ -2125,6 +2042,7 @@ void silc_server_packet_relay_command_reply(SilcServer server,
   SilcClientEntry client;
   SilcClientID *id;
   SilcSocketConnection dst_sock;
+  SilcIDListData idata;
 
   SILC_LOG_DEBUG(("Start"));
 
@@ -2158,10 +2076,11 @@ void silc_server_packet_relay_command_reply(SilcServer server,
   silc_packet_send_prepare(dst_sock, 0, 0, buffer->len);
   silc_buffer_put(dst_sock->outbuf, buffer->data, buffer->len);
 
+  idata = (SilcIDListData)client;
+
   /* Encrypt packet */
-  if (client && client->send_key)
-    silc_packet_encrypt(client->send_key, client->hmac, 
-                       dst_sock->outbuf, buffer->len);
+  silc_packet_encrypt(idata->send_key, idata->hmac, dst_sock->outbuf, 
+                     buffer->len);
     
   /* Send the packet */
   silc_server_packet_send_real(server, dst_sock, FALSE);
@@ -2232,13 +2151,15 @@ void silc_server_free_sock_user_data(SilcServer server,
   switch(sock->type) {
   case SILC_SOCKET_TYPE_CLIENT:
     {
-      SilcClientEntry user_data = (SilcClientEntry )sock->user_data;
+      SilcClientEntry user_data = (SilcClientEntry)sock->user_data;
 
       /* Remove client from all channels */
       silc_server_remove_from_channels(server, sock, user_data);
 
-      /* Free the client entry and everything in it */
       /* XXX must take some info to history before freeing */
+
+      /* Free the client entry and everything in it */
+      silc_idlist_del_data(user_data);
       silc_idlist_del_client(server->local_list, user_data);
       break;
     }
@@ -2253,25 +2174,13 @@ void silc_server_free_sock_user_data(SilcServer server,
     {
       SilcUnknownEntry user_data = (SilcUnknownEntry)sock->user_data;
 
-      if (user_data->send_key)
-       silc_cipher_free(user_data->send_key);
-      if (user_data->receive_key)
-       silc_cipher_free(user_data->receive_key);
-      if (user_data->pkcs)
-       silc_pkcs_free(user_data->pkcs);
-      if (user_data->hmac) {
-       silc_hmac_free(user_data->hmac);
-       memset(user_data->hmac_key, 0, user_data->hmac_key_len);
-       silc_free(user_data->hmac_key);
-      }
+      silc_idlist_del_data(user_data);
       silc_free(user_data);
       break;
     }
   }
 
   sock->user_data = NULL;
-#undef LCC
-#undef LCCC
 }
 
 /* Removes client from all channels it has joined. This is used when
@@ -2485,6 +2394,7 @@ void silc_server_private_message(SilcServer server,
   SilcServerEntry router;
   SilcSocketConnection dst_sock;
   SilcClientEntry client;
+  SilcIDListData idata;
 
   SILC_LOG_DEBUG(("Start"));
 
@@ -2514,19 +2424,21 @@ void silc_server_private_message(SilcServer server,
         "router" of the client is the server who owns the client. Thus
         we will send the packet to that server. */
       router = (SilcServerEntry)dst_sock->user_data;
+      idata = (SilcIDListData)router;
       //      assert(client->router == server->id_entry);
 
       silc_server_private_message_send_internal(server, dst_sock,
-                                               router->send_key,
-                                               router->hmac,
+                                               idata->send_key,
+                                               idata->hmac,
                                                packet);
       goto out;
     }
 
     /* Seems that client really is directly connected to us */
+    idata = (SilcIDListData)client;
     silc_server_private_message_send_internal(server, dst_sock, 
-                                             client->send_key,
-                                             client->hmac, packet);
+                                             idata->send_key,
+                                             idata->hmac, packet);
     goto out;
   }
 
@@ -2538,9 +2450,10 @@ void silc_server_private_message(SilcServer server,
     /* Send to primary route */
     if (router) {
       dst_sock = (SilcSocketConnection)router->connection;
+      idata = (SilcIDListData)router;
       silc_server_private_message_send_internal(server, dst_sock, 
-                                               router->send_key,
-                                               router->hmac, packet);
+                                               idata->send_key,
+                                               idata->hmac, packet);
     }
     goto out;
   }
@@ -2550,12 +2463,13 @@ void silc_server_private_message(SilcServer server,
   if (server->server_type == SILC_ROUTER && !server->standalone) {
     dst_sock = silc_server_get_route(server, id, SILC_ID_CLIENT);
     router = (SilcServerEntry)dst_sock->user_data;
+    idata = (SilcIDListData)router;
 
     /* Get fastest route and send packet. */
     if (router)
       silc_server_private_message_send_internal(server, dst_sock, 
-                                               router->send_key,
-                                               router->hmac, packet);
+                                               idata->send_key,
+                                               idata->hmac, packet);
 
     goto out;
   }
@@ -2831,8 +2745,7 @@ void silc_server_send_notify_on_channels(SilcServer server,
   unsigned int routed_count = 0;
   SilcChannelEntry channel;
   SilcChannelClientEntry chl, chl2;
-  SilcCipher cipher;
-  SilcHmac hmac;
+  SilcIDListData idata;
   SilcBuffer packet;
   unsigned char *data;
   unsigned int data_len;
@@ -2884,8 +2797,7 @@ void silc_server_send_notify_on_channels(SilcServer server,
        
        /* Get data used in packet header encryption, keys and stuff. */
        sock = (SilcSocketConnection)c->router->connection;
-       cipher = c->router->send_key;
-       hmac = c->router->hmac;
+       idata = (SilcIDListData)c->router;
        
        packetdata.dst_id = silc_id_id2str(c->router->id, SILC_ID_SERVER);
        packetdata.dst_id_len = SILC_ID_SERVER_LEN;
@@ -2896,8 +2808,9 @@ void silc_server_send_notify_on_channels(SilcServer server,
 
        /* Send the packet */
        silc_server_packet_send_to_channel_real(server, sock, &packetdata,
-                                               cipher, hmac, data,
-                                               data_len, FALSE, force_send);
+                                               idata->send_key, idata->hmac, 
+                                               data, data_len, FALSE, 
+                                               force_send);
        
        silc_free(packetdata.dst_id);
 
@@ -2916,8 +2829,7 @@ void silc_server_send_notify_on_channels(SilcServer server,
        
        /* Get data used in packet header encryption, keys and stuff. */
        sock = (SilcSocketConnection)c->connection;
-       cipher = c->send_key;
-       hmac = c->hmac;
+       idata = (SilcIDListData)c;
        
        packetdata.dst_id = silc_id_id2str(c->id, SILC_ID_CLIENT);
        packetdata.dst_id_len = SILC_ID_CLIENT_LEN;
@@ -2928,8 +2840,9 @@ void silc_server_send_notify_on_channels(SilcServer server,
 
        /* Send the packet */
        silc_server_packet_send_to_channel_real(server, sock, &packetdata,
-                                               cipher, hmac, data,
-                                               data_len, FALSE, force_send);
+                                               idata->send_key, idata->hmac, 
+                                               data, data_len, FALSE, 
+                                               force_send);
 
        silc_free(packetdata.dst_id);
 
@@ -3216,6 +3129,7 @@ SilcClientEntry silc_server_new_client(SilcServer server,
   SilcIDCacheEntry cache;
   SilcClientID *client_id;
   SilcBuffer reply;
+  SilcIDListData idata;
   char *username = NULL, *realname = NULL, *id_string;
 
   SILC_LOG_DEBUG(("Creating new client"));
@@ -3225,6 +3139,7 @@ SilcClientEntry silc_server_new_client(SilcServer server,
 
   /* Take client entry */
   client = (SilcClientEntry)sock->user_data;
+  idata = (SilcIDListData)client;
 
   /* Fetch the old client cache entry so that we can update it. */
   if (!silc_idcache_find_by_context(server->local_list->clients,
@@ -3244,7 +3159,7 @@ SilcClientEntry silc_server_new_client(SilcServer server,
                           username, &client_id);
 
   /* Update client entry */
-  client->registered = TRUE;
+  idata->registered = TRUE;
   client->nickname = strdup(username);
   client->username = username;
   client->userinfo = realname;
@@ -3288,8 +3203,8 @@ SilcClientEntry silc_server_new_client(SilcServer server,
   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
                          ("Your connection is secured with %s cipher, "
                           "key length %d bits",
-                          client->send_key->cipher->name,
-                          client->send_key->cipher->key_len));
+                          idata->send_key->cipher->name,
+                          idata->send_key->cipher->key_len));
   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
                          ("Your current nickname is %s",
                           client->nickname));
@@ -3316,6 +3231,7 @@ SilcServerEntry silc_server_new_server(SilcServer server,
   SilcServerEntry new_server;
   SilcIDCacheEntry cache;
   SilcServerID *server_id;
+  SilcIDListData idata;
   unsigned char *server_name, *id_string;
   unsigned short id_len;
 
@@ -3327,6 +3243,7 @@ SilcServerEntry silc_server_new_server(SilcServer server,
 
   /* Take server entry */
   new_server = (SilcServerEntry)sock->user_data;
+  idata = (SilcIDListData)new_server;
 
   /* Fetch the old server cache entry so that we can update it. */
   if (!silc_idcache_find_by_context(server->local_list->servers,
@@ -3348,11 +3265,11 @@ SilcServerEntry silc_server_new_server(SilcServer server,
   }
 
   /* Get Server ID */
-  server_id = silc_id_payload_parse_id(id_string, id_len);
+  server_id = silc_id_str2id(id_string, SILC_ID_SERVER);
   silc_free(id_string);
 
   /* Update client entry */
-  new_server->registered = TRUE;
+  idata->registered = TRUE;
   new_server->server_name = server_name;
   new_server->id = server_id;
 
@@ -3365,7 +3282,8 @@ SilcServerEntry silc_server_new_server(SilcServer server,
   /* Distribute the information about new server in the SILC network
      to our router. If we are normal server we won't send anything
      since this connection must be our router connection. */
-  if (server->server_type == SILC_ROUTER && !server->standalone)
+  if (server->server_type == SILC_ROUTER && !server->standalone &&
+      server->id_entry->router->connection != sock)
     silc_server_send_new_id(server, server->id_entry->router->connection,
                            TRUE, new_server->id, SILC_ID_SERVER, 
                            SILC_ID_SERVER_LEN);
@@ -3436,8 +3354,7 @@ void silc_server_new_id(SilcServer server, SilcSocketConnection sock,
       /* Add the client to our local list. We are router and we keep
         cell specific local database of all clients in the cell. */
       idlist = silc_idlist_add_client(id_list, NULL, NULL, NULL,
-                                     id, router, NULL, NULL, 
-                                     NULL, NULL, NULL, router_sock);
+                                     id, router, router_sock);
     }
     break;
 
@@ -3447,9 +3364,8 @@ void silc_server_new_id(SilcServer server, SilcSocketConnection sock,
 
       /* Add the server to our local list. We are router and we keep
         cell specific local database of all servers in the cell. */
-      idlist = silc_idlist_add_server(id_list, NULL, 0,
-                                     id, router, NULL, NULL, 
-                                     NULL, NULL, NULL, router_sock);
+      idlist = silc_idlist_add_server(id_list, NULL, 0, id, router, 
+                                     router_sock);
     }
     break;
 
index 1e3dd56427fa40b92c6b2fa683db49805ec4b36a..edad5b4752671152a7dff0cd0a0d170a05290ceb 100644 (file)
@@ -37,11 +37,11 @@ typedef struct SilcServerStruct *SilcServer;
 /* Connection retry timeout. We implement exponential backoff algorithm
    in connection retry. The interval of timeuot grows when retry count
    grows. */
-#define SILC_SERVER_RETRY_COUNT        3        /* Max retry count */
+#define SILC_SERVER_RETRY_COUNT        4        /* Max retry count */
 #define SILC_SERVER_RETRY_MULTIPLIER   7 / 4    /* Interval growth */
 #define SILC_SERVER_RETRY_RANDOMIZER   2        /* timeout += rnd % 2 */
-#define SILC_SERVER_RETRY_INTERVAL_MIN        /* Min retry timeout */
-#define SILC_SERVER_RETRY_INTERVAL_MAX 30       /* Max generated timeout */
+#define SILC_SERVER_RETRY_INTERVAL_MIN 10       /* Min retry timeout */
+#define SILC_SERVER_RETRY_INTERVAL_MAX 600      /* Max generated timeout */
 
 /* 
    Silc Server Params.
index 25c562f49df47c8f713b5d72637685432090bd94..ffc7e118ab474d1ccc88a71b3d4f033d67eaf081 100644 (file)
 
        Format:
 
-       +<Remote address or name>:<auth method>:<password/key/???>:<Port>:<Version ID>:<Class>
+       +<Remote address or name>:<auth method>:<password/key/???>:
+       <Port>:<Version ID>:<Class>:<Initiator>
 
    <DenyConnection>
 
@@ -169,7 +170,7 @@ SilcConfigServerSection silc_config_server_sections[] = {
   { "[ServerConnection]", 
     SILC_CONFIG_SERVER_SECTION_TYPE_SERVER_CONNECTION, 6 },
   { "[RouterConnection]", 
-    SILC_CONFIG_SERVER_SECTION_TYPE_ROUTER_CONNECTION, 6 },
+    SILC_CONFIG_SERVER_SECTION_TYPE_ROUTER_CONNECTION, 7 },
   { "[AdminConnection]", 
     SILC_CONFIG_SERVER_SECTION_TYPE_ADMIN_CONNECTION, 5 },
   { "[DenyConnection]", 
@@ -900,6 +901,17 @@ int silc_config_server_parse_lines(SilcConfigServer config,
        silc_free(tmp);
       }
 
+      /* Get whether we are initiator or not */
+      ret = silc_config_get_token(line, &tmp);
+      if (ret < 0)
+       break;
+      if (ret) {
+       config->routers->initiator = atoi(tmp);
+       if (config->routers->initiator != 0)
+         config->routers->initiator = TRUE;
+       silc_free(tmp);
+      }
+
       check = TRUE;
       checkmask |= (1L << pc->section->type);
       break;
index 5b7a1d54cd2bc70859ccc73b90a06565a9f4f5be..e4c76d66f812b785d25c99c46dd074bafc584ec3 100644 (file)
@@ -115,6 +115,7 @@ typedef struct SilcConfigServerSectionServerConnectionStruct {
   unsigned short port;
   char *version;
   unsigned int class;
+  int initiator;
   struct SilcConfigServerSectionServerConnectionStruct *next;
   struct SilcConfigServerSectionServerConnectionStruct *prev;
 } SilcConfigServerSectionServerConnection;
index bf4d2408af814e94ed459d4349f434d6eaa4f899..08d85faefb2daf3cea152f65d0233af6d8076bf2 100644 (file)
@@ -44,7 +44,7 @@ errorlogfile:silcd2.log:10000
 10.2.1.6:passwd:priikone:1335:1:1
 
 [RouterConnection]
-#10.2.1.6:passwd:priikone:1333:1:1
+10.2.1.6:passwd:priikone:1333:1:1:0
 
 [DenyConnection]
 [RedirectClient]