updates.
[silc.git] / apps / silcd / server.c
index 75c9cdc37a6d0859b1b2c43263c838449eb65192..609b02df49ca39131d1c1bd73c4e2e634e71743f 100644 (file)
@@ -74,18 +74,8 @@ void silc_server_free(SilcServer server)
 {
   if (server) {
 #ifdef SILC_SIM
-    SilcSimContext *sim;
-#endif
+    SilcSim sim;
 
-    silc_free(server->local_list);
-    silc_free(server->global_list);
-    if (server->rng)
-      silc_rng_free(server->rng);
-
-    if (server->pkcs)
-      silc_pkcs_free(server->pkcs);
-
-#ifdef SILC_SIM
     while ((sim = silc_dlist_get(server->sim)) != SILC_LIST_END) {
       silc_dlist_del(server->sim, sim);
       silc_sim_free(sim);
@@ -93,9 +83,23 @@ void silc_server_free(SilcServer server)
     silc_dlist_uninit(server->sim);
 #endif
 
+    if (server->rng)
+      silc_rng_free(server->rng);
+    if (server->pkcs)
+      silc_pkcs_free(server->pkcs);
     if (server->pending_commands)
       silc_dlist_uninit(server->pending_commands);
+    if (server->id_entry)
+      silc_idlist_del_server(server->local_list, server->id_entry);
 
+    silc_idcache_free(server->local_list->clients);
+    silc_idcache_free(server->local_list->servers);
+    silc_idcache_free(server->local_list->channels);
+    silc_idcache_free(server->global_list->clients);
+    silc_idcache_free(server->global_list->servers);
+    silc_idcache_free(server->global_list->channels);
+
+    silc_free(server->sockets);
     silc_free(server);
   }
 }
@@ -157,8 +161,7 @@ int silc_server_init(SilcServer server)
 
   /* Create a listening server */
   sock = silc_net_create_server(server->config->server_info->port,
-                              server->config->server_info->server_ip);
-  /* XXX What if I want my errno? Where is my errno?!?  -Johnny */
+                               server->config->server_info->server_ip);
   if (sock < 0) {
     SILC_LOG_ERROR(("Could not create server listener: %s on %hu",
                    server->config->server_info->server_ip,
@@ -184,7 +187,7 @@ int silc_server_init(SilcServer server)
      all connections will have entry in this table (it is a table of
      pointers to the actual object that is allocated individually
      later). */
-  server->sockets = silc_calloc(SILC_SERVER_MAX_CONNECTIONS,
+  server->sockets = silc_calloc(server->config->param.connections_max,
                                sizeof(*server->sockets));
 
   do {
@@ -232,8 +235,7 @@ int silc_server_init(SilcServer server)
        For now, NULL is sent as router. This allocates new entry to
        the ID list. */
     id_entry =
-      silc_idlist_add_server(server->local_list,
-                            server->config->server_info->server_name,
+      silc_idlist_add_server(server->local_list, strdup(server->server_name),
                             server->server_type, server->id, NULL, NULL);
     if (!id_entry) {
       SILC_LOG_ERROR(("Could not add ourselves to cache"));
@@ -252,7 +254,7 @@ int silc_server_init(SilcServer server)
   silc_server_protocols_register();
 
   /* Initialize the scheduler. */
-  server->schedule = silc_schedule_init(SILC_SERVER_MAX_CONNECTIONS);
+  server->schedule = silc_schedule_init(server->config->param.connections_max);
   if (!server->schedule)
     goto err;
 
@@ -282,7 +284,7 @@ int silc_server_init(SilcServer server)
   /* If server connections has been configured then we must be router as
      normal server cannot have server connections, only router connections. */
   if (server->config->servers) {
-    SilcServerConfigSectionServer *ptr = server->config->servers;
+    SilcServerConfigServer *ptr = server->config->servers;
 
     server->server_type = SILC_ROUTER;
     while (ptr) {
@@ -477,6 +479,7 @@ void silc_server_start_key_exchange(SilcServer server,
   SilcSocketConnection newsocket;
   SilcProtocol protocol;
   SilcServerKEInternalContext *proto_ctx;
+  SilcServerConfigRouter *conn = sconn->conn;
   void *context;
 
   /* Cancel any possible retry timeouts */
@@ -507,6 +510,12 @@ void silc_server_start_key_exchange(SilcServer server,
   proto_ctx->rng = server->rng;
   proto_ctx->responder = FALSE;
 
+  /* Set Key Exchange flags from configuration, but fall back to global
+     settings too. */
+  SILC_GET_SKE_FLAGS(conn, proto_ctx);
+  if (server->config->param.key_exchange_pfs)
+    proto_ctx->flags |= SILC_SKE_SP_FLAG_PFS;
+
   /* Perform key exchange protocol. silc_server_connect_to_router_second
      will be called after the protocol is finished. */
   silc_protocol_alloc(SILC_PROTOCOL_SERVER_KEY_EXCHANGE, 
@@ -519,7 +528,7 @@ void silc_server_start_key_exchange(SilcServer server,
   proto_ctx->timeout_task = 
     silc_schedule_task_add(server->schedule, sock, 
                           silc_server_timeout_remote,
-                          server, 60, 0, /* XXX hardcoded */
+                          server, server->config->key_exchange_timeout, 0,
                           SILC_TASK_TIMEOUT,
                           SILC_TASK_PRI_LOW);
 
@@ -545,9 +554,8 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_retry)
 {
   SilcServerConnection sconn = (SilcServerConnection)context;
   SilcServer server = sconn->server;
-  SilcServerConfigSectionConnectionParam *param;
-
-  param = (sconn->param ? sconn->param : &server->config->param);
+  SilcServerConfigConnParams *param = 
+    (sconn->param ? sconn->param : &server->config->param);
 
   SILC_LOG_INFO(("Retrying connecting to a router"));
 
@@ -564,7 +572,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_retry)
     silc_rng_get_rn32(server->rng) % SILC_SERVER_RETRY_RANDOMIZER;
 
   /* If we've reached max retry count, give up. */
-  if (sconn->retry_count > param->reconnect_count && 
+  if (sconn->retry_count > param->reconnect_count &&
       param->reconnect_keep_trying == FALSE) {
     SILC_LOG_ERROR(("Could not connect to router, giving up"));
     silc_free(sconn->remote_host);
@@ -620,7 +628,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router)
 {
   SilcServer server = (SilcServer)context;
   SilcServerConnection sconn;
-  SilcServerConfigSectionRouter *ptr;
+  SilcServerConfigRouter *ptr;
 
   SILC_LOG_DEBUG(("Connecting to router(s)"));
 
@@ -690,7 +698,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_second)
   SilcServerConnection sconn = (SilcServerConnection)ctx->context;
   SilcSocketConnection sock = ctx->sock;
   SilcServerConnAuthInternalContext *proto_ctx;
-  SilcServerConfigSectionRouter *conn = NULL;
+  SilcServerConfigRouter *conn = NULL;
 
   SILC_LOG_DEBUG(("Start"));
 
@@ -760,20 +768,18 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_second)
     conn = sconn->conn;
 
   if (conn) {
-    /* Match found. Use the configured authentication method */
+    /* Match found. Use the configured authentication method. Take only
+       the passphrase, since for public key auth we automatically use
+       our local key pair. */
     if (conn->passphrase) {
-      if (conn->publickey && !server->config->prefer_passphrase_auth) {
-       proto_ctx->auth_data = conn->publickey;
-       proto_ctx->auth_data_len = 0;
+      if (conn->publickeys && !server->config->prefer_passphrase_auth) {
        proto_ctx->auth_meth = SILC_AUTH_PUBLIC_KEY;
       } else {
        proto_ctx->auth_data = strdup(conn->passphrase);
        proto_ctx->auth_data_len = strlen(conn->passphrase);
        proto_ctx->auth_meth = SILC_AUTH_PASSWORD;
       }
-    } else if (conn->publickey) {
-      proto_ctx->auth_data = conn->publickey;
-      proto_ctx->auth_data_len = 0;
+    } else if (conn->publickeys) {
       proto_ctx->auth_meth = SILC_AUTH_PUBLIC_KEY;
     } else {
       proto_ctx->auth_meth = SILC_AUTH_NONE;
@@ -816,7 +822,8 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_second)
   proto_ctx->timeout_task =
     silc_schedule_task_add(server->schedule, sock->sock,
                           silc_server_timeout_remote,
-                          (void *)server, 15, 0, /* XXX hardcoded */
+                          (void *)server, 
+                          server->config->conn_auth_timeout, 0, 
                           SILC_TASK_TIMEOUT,
                           SILC_TASK_PRI_LOW);
 
@@ -839,9 +846,9 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final)
   SilcBuffer packet;
   SilcServerHBContext hb_context;
   unsigned char *id_string;
-  uint32 id_len;
+  SilcUInt32 id_len;
   SilcIDListData idata;
-  SilcServerConfigSectionConnectionParam *param;
+  SilcServerConfigConnParams *param;
 
   SILC_LOG_DEBUG(("Start"));
 
@@ -908,6 +915,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final)
                                    SILC_ROUTER, ctx->dest_id, NULL, sock);
   if (!id_entry) {
     silc_free(ctx->dest_id);
+    SILC_LOG_ERROR(("Cannot add new server entry to cache"));
     silc_server_disconnect_remote(server, sock, "Server closed connection: "
                                  "Authentication failed");
     goto out;
@@ -923,8 +931,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final)
   param = (sconn->param ? sconn->param : &server->config->param);
 
   /* Perform keepalive. The `hb_context' will be freed automatically
-     when finally calling the silc_socket_free function. XXX hardcoded 
-     timeout!! */
+     when finally calling the silc_socket_free function. */
   hb_context = silc_calloc(1, sizeof(*hb_context));
   hb_context->server = server;
   silc_socket_set_heartbeat(sock, param->keepalive_secs, hb_context,
@@ -932,7 +939,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final)
                            server->schedule);
 
   /* Register re-key timeout */
-  idata->rekey->timeout = 3600; /* XXX hardcoded */
+  idata->rekey->timeout = param->key_exchange_rekey;
   idata->rekey->context = (void *)server;
   silc_schedule_task_add(server->schedule, sock->sock, 
                         silc_server_rekey_callback,
@@ -1002,8 +1009,10 @@ silc_server_accept_new_connection_lookup(SilcSocketConnection sock,
 {
   SilcServer server = (SilcServer)context;
   SilcServerKEInternalContext *proto_ctx;
-  void *cconfig, *sconfig, *rconfig;
-  SilcServerConfigSectionDeny *deny;
+  SilcServerConfigClient *cconfig = NULL;
+  SilcServerConfigServer *sconfig = NULL;
+  SilcServerConfigRouter *rconfig = NULL;
+  SilcServerConfigDeny *deny;
   int port;
 
   SILC_LOG_DEBUG(("Start"));
@@ -1028,15 +1037,15 @@ silc_server_accept_new_connection_lookup(SilcSocketConnection sock,
      later when outgoing data is available. */
   SILC_REGISTER_CONNECTION_FOR_IO(sock->sock);
 
-  SILC_LOG_INFO(("Incoming connection from %s (%s)", sock->hostname,
+  SILC_LOG_INFO(("Incoming connection %s (%s)", sock->hostname,
                 sock->ip));
 
   port = server->sockets[server->sock]->port; /* Listenning port */
 
   /* Check whether this connection is denied to connect to us. */
-  deny = silc_server_config_find_denied(server, sock->ip, port);
+  deny = silc_server_config_find_denied(server, sock->ip);
   if (!deny)
-    deny = silc_server_config_find_denied(server, sock->hostname, port);
+    deny = silc_server_config_find_denied(server, sock->hostname);
   if (deny) {
     /* The connection is denied */
     SILC_LOG_INFO(("Connection %s (%s) is denied", 
@@ -1052,13 +1061,16 @@ silc_server_accept_new_connection_lookup(SilcSocketConnection sock,
   /* Check whether we have configred this sort of connection at all. We
      have to check all configurations since we don't know what type of
      connection this is. */
-  if (!(cconfig = silc_server_config_find_client(server, sock->ip, port)))
-    cconfig = silc_server_config_find_client(server, sock->hostname, port);
+  if (!(cconfig = silc_server_config_find_client(server, sock->ip)))
+    cconfig = silc_server_config_find_client(server, sock->hostname);
   if (!(sconfig = silc_server_config_find_server_conn(server, sock->ip)))
     sconfig = silc_server_config_find_server_conn(server, sock->hostname);
-  if (!(rconfig = silc_server_config_find_router_conn(server, sock->ip, port)))
-    rconfig = silc_server_config_find_router_conn(server, sock->hostname, 
-                                                 sock->port);
+  if (server->server_type == SILC_ROUTER) {
+    if (!(rconfig = silc_server_config_find_router_conn(server, 
+                                                       sock->ip, port)))
+      rconfig = silc_server_config_find_router_conn(server, sock->hostname, 
+                                                   sock->port);
+  }
   if (!cconfig && !sconfig && !rconfig) {
     SILC_LOG_INFO(("Connection %s (%s) is not allowed", sock->hostname, 
                   sock->ip));
@@ -1082,6 +1094,15 @@ silc_server_accept_new_connection_lookup(SilcSocketConnection sock,
   proto_ctx->sconfig = sconfig;
   proto_ctx->rconfig = rconfig;
 
+  /* Take flags for key exchange. Since we do not know what type of connection
+     this is, we go through all found configuratios and use the global ones
+     as well. This will result always into strictest key exchange flags. */
+  SILC_GET_SKE_FLAGS(cconfig, proto_ctx);
+  SILC_GET_SKE_FLAGS(sconfig, proto_ctx);
+  SILC_GET_SKE_FLAGS(rconfig, proto_ctx);
+  if (server->config->param.key_exchange_pfs)
+    proto_ctx->flags |= SILC_SKE_SP_FLAG_PFS;
+
   /* Prepare the connection for key exchange protocol. We allocate the
      protocol but will not start it yet. The connector will be the
      initiator of the protocol thus we will wait for initiation from 
@@ -1092,13 +1113,12 @@ silc_server_accept_new_connection_lookup(SilcSocketConnection sock,
                      silc_server_accept_new_connection_second);
 
   /* Register a timeout task that will be executed if the connector
-     will not start the key exchange protocol within 60 seconds. For
-     now, this is a hard coded limit. After the timeout the connection will
-     be closed if the key exchange protocol has not been started. */
+     will not start the key exchange protocol within specified timeout
+     and the connection will be closed. */
   proto_ctx->timeout_task = 
     silc_schedule_task_add(server->schedule, sock->sock, 
                           silc_server_timeout_remote,
-                          context, 60, 0, /* XXX hardcoded */
+                          context, server->config->key_exchange_timeout, 0,
                           SILC_TASK_TIMEOUT,
                           SILC_TASK_PRI_LOW);
 }
@@ -1123,12 +1143,12 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection)
     return;
   }
 
-  /* Check max connections */
-  if (sock > SILC_SERVER_MAX_CONNECTIONS) {
-    SILC_LOG_ERROR(("Refusing connection, server is full"));
+  /* Check for maximum allowed connections */
+  if (sock > server->config->param.connections_max) {
+    SILC_LOG_ERROR(("Refusing connection, server is full, try again later"));
     server->stat.conn_failures++;
     return;
-  }
+  }  
 
   /* Set socket options */
   silc_net_set_socket_nonblock(sock);
@@ -1246,7 +1266,8 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_second)
   proto_ctx->timeout_task = 
     silc_schedule_task_add(server->schedule, sock->sock, 
                           silc_server_timeout_remote,
-                          (void *)server, 60, 0, /* XXX hardcoded */
+                          (void *)server, 
+                          server->config->conn_auth_timeout, 0, 
                           SILC_TASK_TIMEOUT,
                           SILC_TASK_PRI_LOW);
 }
@@ -1265,7 +1286,7 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
   SilcServerHBContext hb_context;
   SilcUnknownEntry entry = (SilcUnknownEntry)sock->user_data;
   void *id_entry;
-  uint32 hearbeat_timeout = SILC_SERVER_KEEPALIVE;
+  SilcUInt32 hearbeat_timeout = server->config->param.keepalive_secs;
 
   SILC_LOG_DEBUG(("Start"));
 
@@ -1294,10 +1315,18 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
   case SILC_SOCKET_TYPE_CLIENT:
     {
       SilcClientEntry client;
-      SilcServerConfigSectionClient *conn = ctx->cconfig;
+      SilcServerConfigClient *conn = ctx->cconfig;
+
+      /* Verify whether this connection is after all allowed to connect */
+      if (!silc_server_connection_allowed(server, sock, ctx->conn_type,
+                                         &server->config->param,
+                                         conn->param, ctx->ske)) {
+       server->stat.auth_failures++;
+       goto out;
+      }
 
       SILC_LOG_DEBUG(("Remote host is client"));
-      SILC_LOG_INFO(("Connection from %s (%s) is client", sock->hostname,
+      SILC_LOG_INFO(("Connection %s (%s) is client", sock->hostname,
                     sock->ip));
 
       /* Add the client to the client ID cache. The nickname and Client ID
@@ -1338,29 +1367,50 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
       bool backup_local = FALSE;
       bool backup_router = FALSE;
       char *backup_replace_ip = NULL;
-      uint16 backup_replace_port = 0;
-      SilcServerConfigSectionServer *sconn = ctx->sconfig;
-      SilcServerConfigSectionRouter *rconn = ctx->rconfig;
-
-      if (ctx->conn_type == SILC_SOCKET_TYPE_ROUTER && rconn) {
-       initiator = rconn->initiator;
-       backup_local = rconn->backup_local;
-       backup_router = rconn->backup_router;
-       backup_replace_ip = rconn->backup_replace_ip;
-       backup_replace_port = rconn->backup_replace_port;
-
-       if (rconn->param) {
-         if (rconn->param->keepalive_secs)
-           hearbeat_timeout = rconn->param->keepalive_secs;
+      SilcUInt16 backup_replace_port = 0;
+      SilcServerConfigServer *sconn = ctx->sconfig;
+      SilcServerConfigRouter *rconn = ctx->rconfig;
+
+      if (ctx->conn_type == SILC_SOCKET_TYPE_ROUTER) {
+       /* Verify whether this connection is after all allowed to connect */
+       if (!silc_server_connection_allowed(server, sock, ctx->conn_type,
+                                           &server->config->param,
+                                           rconn ? rconn->param : NULL, 
+                                           ctx->ske)) {
+         server->stat.auth_failures++;
+         goto out;
+       }
+
+       if (rconn) {
+         if (rconn->param) {
+           if (rconn->param->keepalive_secs)
+             hearbeat_timeout = rconn->param->keepalive_secs;
+         }
+
+         initiator = rconn->initiator;
+         backup_local = rconn->backup_local;
+         backup_router = rconn->backup_router;
+         backup_replace_ip = rconn->backup_replace_ip;
+         backup_replace_port = rconn->backup_replace_port;
        }
       }
 
-      if (ctx->conn_type == SILC_SOCKET_TYPE_SERVER && sconn) {
-       backup_router = sconn->backup_router;
+      if (ctx->conn_type == SILC_SOCKET_TYPE_SERVER) {
+       /* Verify whether this connection is after all allowed to connect */
+       if (!silc_server_connection_allowed(server, sock, ctx->conn_type,
+                                           &server->config->param,
+                                           sconn ? sconn->param : NULL, 
+                                           ctx->ske)) {
+         server->stat.auth_failures++;
+         goto out;
+       }
+       if (sconn) {
+         if (sconn->param) {
+           if (sconn->param->keepalive_secs)
+             hearbeat_timeout = sconn->param->keepalive_secs;
+         }
 
-       if (sconn->param) {
-         if (sconn->param->keepalive_secs)
-           hearbeat_timeout = sconn->param->keepalive_secs;
+         backup_router = sconn->backup_router;
        }
       }
 
@@ -1368,7 +1418,7 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
                      ctx->conn_type == SILC_SOCKET_TYPE_SERVER ? 
                      "server" : (backup_router ? 
                                  "backup router" : "router")));
-      SILC_LOG_INFO(("Connection from %s (%s) is %s", sock->hostname,
+      SILC_LOG_INFO(("Connection %s (%s) is %s", sock->hostname,
                     sock->ip, ctx->conn_type == SILC_SOCKET_TYPE_SERVER ? 
                     "server" : (backup_router ? 
                                 "backup router" : "router")));
@@ -1486,7 +1536,7 @@ SILC_TASK_CALLBACK(silc_server_packet_process)
   SilcIDListData idata;
   SilcCipher cipher = NULL;
   SilcHmac hmac = NULL;
-  uint32 sequence = 0;
+  SilcUInt32 sequence = 0;
   int ret;
 
   if (!sock)
@@ -1503,9 +1553,6 @@ SILC_TASK_CALLBACK(silc_server_packet_process)
 
     server->stat.packets_sent++;
 
-    if (sock->outbuf->data - sock->outbuf->head)
-     silc_buffer_push(sock->outbuf, sock->outbuf->data - sock->outbuf->head);
-
     /* Send the packet */
     ret = silc_packet_send(sock, TRUE);
 
@@ -1588,7 +1635,7 @@ SILC_TASK_CALLBACK(silc_server_packet_process)
   /* 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 disonnected connection"));
+    SILC_LOG_DEBUG(("Ignoring read data from disconnected connection"));
     return;
   }
 
@@ -1792,6 +1839,12 @@ void silc_server_packet_parse_type(SilcServer server,
     SILC_LOG_DEBUG(("Disconnect packet"));
     if (packet->flags & SILC_PACKET_FLAG_LIST)
       break;
+    if (silc_string_is_ascii(packet->buffer->data, packet->buffer->len)) {
+      /* Duplicate to null terminate the string. */
+      char *message = silc_memdup(packet->buffer->data, packet->buffer->len);
+      SILC_LOG_ERROR(("%s", message));
+      silc_free(message);
+    }
     break;
 
   case SILC_PACKET_SUCCESS:
@@ -2212,7 +2265,7 @@ void silc_server_packet_parse_type(SilcServer server,
 /* Creates connection to a remote router. */
 
 void silc_server_create_connection(SilcServer server,
-                                  const char *remote_host, uint32 port)
+                                  const char *remote_host, SilcUInt32 port)
 {
   SilcServerConnection sconn;
 
@@ -2305,6 +2358,7 @@ void silc_server_disconnect_remote(SilcServer server,
      is tried to be sent immediately. */
   silc_server_packet_send(server, sock, SILC_PACKET_DISCONNECT, 0,  
                          buf, strlen(buf), TRUE);
+  silc_server_packet_queue_purge(server, sock);
 
   /* Mark the connection to be disconnected */
   SILC_SET_DISCONNECTED(sock);
@@ -2566,6 +2620,7 @@ void silc_server_remove_from_channels(SilcServer server,
 
     /* Remove client from channel's client list */
     silc_hash_table_del(channel->user_list, chl->client);
+    channel->user_count--;
 
     /* If there is no global users on the channel anymore mark the channel
        as local channel. Do not check if the removed client is local client. */
@@ -2603,6 +2658,7 @@ void silc_server_remove_from_channels(SilcServer server,
        while (silc_hash_table_get(&htl2, NULL, (void *)&chl2)) {
          silc_hash_table_del(chl2->client->channels, channel);
          silc_hash_table_del(channel->user_list, chl2->client);
+         channel->user_count--;
          silc_free(chl2);
        }
        silc_hash_table_list_reset(&htl2);
@@ -2690,6 +2746,7 @@ int silc_server_remove_from_one_channel(SilcServer server,
 
   /* Remove client from channel's client list */
   silc_hash_table_del(channel->user_list, chl->client);
+  channel->user_count--;
   
   /* If there is no global users on the channel anymore mark the channel
      as local channel. Do not check if the client is local client. */
@@ -2726,6 +2783,7 @@ int silc_server_remove_from_one_channel(SilcServer server,
       while (silc_hash_table_get(&htl2, NULL, (void *)&chl2)) {
        silc_hash_table_del(chl2->client->channels, channel);
        silc_hash_table_del(channel->user_list, chl2->client);
+       channel->user_count--;
        silc_free(chl2);
       }
       silc_hash_table_list_reset(&htl2);
@@ -2764,6 +2822,9 @@ SILC_TASK_CALLBACK(silc_server_timeout_remote)
   if (!sock)
     return;
 
+  SILC_LOG_ERROR(("No response from %s (%s), Connection timeout",
+                 sock->hostname, sock->ip));
+
   /* If we have protocol active we must assure that we call the protocol's
      final callback so that all the memory is freed. */
   if (sock->protocol) {
@@ -2946,11 +3007,11 @@ SILC_TASK_CALLBACK(silc_server_channel_key_rekey)
 
 bool silc_server_create_channel_key(SilcServer server, 
                                    SilcChannelEntry channel,
-                                   uint32 key_len)
+                                   SilcUInt32 key_len)
 {
   int i;
   unsigned char channel_key[32], hash[32];
-  uint32 len;
+  SilcUInt32 len;
 
   SILC_LOG_DEBUG(("Generating channel key"));
 
@@ -2986,8 +3047,7 @@ bool silc_server_create_channel_key(SilcServer server,
 
   /* Save the key */
   channel->key_len = len * 8;
-  channel->key = silc_calloc(len, sizeof(*channel->key));
-  memcpy(channel->key, channel_key, len);
+  channel->key = silc_memdup(channel_key, len);
   memset(channel_key, 0, sizeof(channel_key));
 
   /* Generate HMAC key from the channel key data and set it */
@@ -3010,7 +3070,8 @@ bool silc_server_create_channel_key(SilcServer server,
     channel->rekey->task = 
       silc_schedule_task_add(server->schedule, 0, 
                             silc_server_channel_key_rekey,
-                            (void *)channel->rekey, 3600, 0,
+                            (void *)channel->rekey, 
+                            server->config->channel_rekey_secs, 0,
                             SILC_TASK_TIMEOUT,
                             SILC_TASK_PRI_NORMAL);
   }
@@ -3029,7 +3090,7 @@ SilcChannelEntry silc_server_save_channel_key(SilcServer server,
   SilcChannelKeyPayload payload = NULL;
   SilcChannelID *id = NULL;
   unsigned char *tmp, hash[32];
-  uint32 tmp_len;
+  SilcUInt32 tmp_len;
   char *cipher;
 
   SILC_LOG_DEBUG(("Start"));
@@ -3097,8 +3158,7 @@ SilcChannelEntry silc_server_save_channel_key(SilcServer server,
 
   /* Save the key */
   channel->key_len = tmp_len * 8;
-  channel->key = silc_calloc(tmp_len, sizeof(unsigned char));
-  memcpy(channel->key, tmp, tmp_len);
+  channel->key = silc_memdup(tmp, tmp_len);
   silc_cipher_set_key(channel->channel_key, tmp, channel->key_len);
 
   /* Generate HMAC key from the channel key data and set it */
@@ -3122,7 +3182,8 @@ SilcChannelEntry silc_server_save_channel_key(SilcServer server,
     channel->rekey->task = 
       silc_schedule_task_add(server->schedule, 0, 
                             silc_server_channel_key_rekey,
-                            (void *)channel->rekey, 3600, 0,
+                            (void *)channel->rekey, 
+                            server->config->channel_rekey_secs, 0,
                             SILC_TASK_TIMEOUT,
                             SILC_TASK_PRI_NORMAL);
   }
@@ -3201,7 +3262,7 @@ static void silc_server_announce_get_servers(SilcServer server,
 }
 
 static SilcBuffer 
-silc_server_announce_encode_notify(SilcNotifyType notify, uint32 argc, ...)
+silc_server_announce_encode_notify(SilcNotifyType notify, SilcUInt32 argc, ...)
 {
   va_list ap;
   SilcBuffer p;
@@ -3451,7 +3512,7 @@ void silc_server_announce_get_channels(SilcServer server,
                                       SilcBuffer *channels,
                                       SilcBuffer *channel_users,
                                       SilcBuffer **channel_users_modes,
-                                      uint32 *channel_users_modes_c,
+                                      SilcUInt32 *channel_users_modes_c,
                                       SilcBuffer **channel_topics,
                                       SilcChannelID ***channel_ids,
                                       unsigned long creation_time)
@@ -3460,8 +3521,8 @@ void silc_server_announce_get_channels(SilcServer server,
   SilcIDCacheEntry id_cache;
   SilcChannelEntry channel;
   unsigned char *cid;
-  uint32 id_len;
-  uint16 name_len;
+  SilcUInt32 id_len;
+  SilcUInt16 name_len;
   int len;
   int i = *channel_users_modes_c;
   bool announce;
@@ -3548,7 +3609,7 @@ void silc_server_announce_channels(SilcServer server,
   SilcBuffer channels = NULL, channel_users = NULL;
   SilcBuffer *channel_users_modes = NULL;
   SilcBuffer *channel_topics = NULL;
-  uint32 channel_users_modes_c = 0;
+  SilcUInt32 channel_users_modes_c = 0;
   SilcChannelID **channel_ids = NULL;
 
   SILC_LOG_DEBUG(("Announcing channels and channel users"));
@@ -3670,14 +3731,14 @@ void silc_server_get_users_on_channel(SilcServer server,
                                      SilcChannelEntry channel,
                                      SilcBuffer *user_list,
                                      SilcBuffer *mode_list,
-                                     uint32 *user_count)
+                                     SilcUInt32 *user_count)
 {
   SilcChannelClientEntry chl;
   SilcHashTableList htl;
   SilcBuffer client_id_list;
   SilcBuffer client_mode_list;
   SilcBuffer idp;
-  uint32 list_count = 0, len = 0;
+  SilcUInt32 list_count = 0, len = 0;
 
   silc_hash_table_list(channel->user_list, &htl);
   while (silc_hash_table_get(&htl, NULL, (void *)&chl))
@@ -3723,11 +3784,11 @@ void silc_server_save_users_on_channel(SilcServer server,
                                       SilcClientID *noadd,
                                       SilcBuffer user_list,
                                       SilcBuffer mode_list,
-                                      uint32 user_count)
+                                      SilcUInt32 user_count)
 {
   int i;
-  uint16 idp_len;
-  uint32 mode;
+  SilcUInt16 idp_len;
+  SilcUInt32 mode;
   SilcClientID *client_id;
   SilcClientEntry client;
   SilcIDCacheEntry cache;
@@ -3739,7 +3800,7 @@ void silc_server_save_users_on_channel(SilcServer server,
     /* Client ID */
     SILC_GET16_MSB(idp_len, user_list->data + 2);
     idp_len += 4;
-    client_id = silc_id_payload_parse_id(user_list->data, idp_len);
+    client_id = silc_id_payload_parse_id(user_list->data, idp_len, NULL);
     silc_buffer_pull(user_list, idp_len);
     if (!client_id)
       continue;
@@ -3794,7 +3855,7 @@ void silc_server_save_users_on_channel(SilcServer server,
 
     silc_free(client_id);
 
-    if (!silc_server_client_on_channel(client, channel)) {
+    if (!silc_server_client_on_channel(client, channel, NULL)) {
       /* Client was not on the channel, add it. */
       SilcChannelClientEntry chl = silc_calloc(1, sizeof(*chl));
       chl->client = client;
@@ -3802,6 +3863,7 @@ void silc_server_save_users_on_channel(SilcServer server,
       chl->channel = channel;
       silc_hash_table_add(channel->user_list, chl->client, chl);
       silc_hash_table_add(client->channels, chl->channel, chl);
+      channel->user_count++;
     }
   }
 }
@@ -3813,7 +3875,7 @@ void silc_server_save_users_on_channel(SilcServer server,
 
 SilcSocketConnection silc_server_get_client_route(SilcServer server,
                                                  unsigned char *id_data,
-                                                 uint32 id_len,
+                                                 SilcUInt32 id_len,
                                                  SilcClientID *client_id,
                                                  SilcIDListData *idata)
 {
@@ -3898,8 +3960,8 @@ SilcBuffer silc_server_get_client_channel_list(SilcServer server,
   SilcChannelClientEntry chl;
   SilcHashTableList htl;
   unsigned char *cid;
-  uint32 id_len;
-  uint16 name_len;
+  SilcUInt32 id_len;
+  SilcUInt16 name_len;
   int len;
 
   silc_hash_table_list(client->channels, &htl);