Fixed TOPIC_SET, CMODE_CHANGE notifys and New Channel packet
[silc.git] / apps / silcd / server.c
index bbc25aa115279aedc840ab3f8ce76e185394953a..ee5765eeb5fe2143aa5d82c5aae7b88ac033d1cd 100644 (file)
@@ -77,50 +77,63 @@ int silc_server_alloc(SilcServer *new_server)
 
 void silc_server_free(SilcServer server)
 {
-  if (server) {
+  if (!server)
+    return;
+
 #ifdef SILC_SIM
+  {
     SilcSim sim;
-
+    
     while ((sim = silc_dlist_get(server->sim)) != SILC_LIST_END) {
       silc_dlist_del(server->sim, sim);
       silc_sim_free(sim);
     }
     silc_dlist_uninit(server->sim);
+  }
 #endif
 
-    silc_server_config_unref(&server->config_ref);
-    if (server->rng)
-      silc_rng_free(server->rng);
-    if (server->pkcs)
-      silc_pkcs_free(server->pkcs);
-    if (server->public_key)
-      silc_pkcs_public_key_free(server->public_key);
-    if (server->private_key)
-      silc_pkcs_private_key_free(server->private_key);
-    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_hash_table_free(server->watcher_list);
-
-    silc_free(server->sockets);
-    silc_free(server);
-  }
+  silc_server_config_unref(&server->config_ref);
+  if (server->rng)
+    silc_rng_free(server->rng);
+  if (server->pkcs)
+    silc_pkcs_free(server->pkcs);
+  if (server->public_key)
+    silc_pkcs_public_key_free(server->public_key);
+  if (server->private_key)
+    silc_pkcs_private_key_free(server->private_key);
+  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_hash_table_free(server->watcher_list);
+
+  silc_hash_free(server->md5hash);
+  silc_hash_free(server->sha1hash);
+  silc_hmac_unregister_all();
+  silc_hash_unregister_all();
+  silc_cipher_unregister_all();
+  silc_pkcs_unregister_all();
+
+  silc_free(server->local_list);
+  silc_free(server->global_list);
+  silc_free(server->server_name);
+  silc_free(server->id_string);
+  silc_free(server->purge_i);
+  silc_free(server->purge_g);
+  silc_free(server);
 }
 
-/* Opens a listening port.
-   XXX This function will become more general and will support multiple
-   listening ports */
+/* Creates a new server listener. */
 
 static bool silc_server_listen(SilcServer server, const char *server_ip,
-                               SilcUInt16 port, int *sock)
+                              SilcUInt16 port, int *sock)
 {
   *sock = silc_net_create_server(port, server_ip);
   if (*sock < 0) {
@@ -132,15 +145,16 @@ static bool silc_server_listen(SilcServer server, const char *server_ip,
 }
 
 /* Adds a secondary listener. */
+
 bool silc_server_init_secondary(SilcServer server)
 {
-  int sock=0, sock_list[server->config->param.connections_max];
+  int sock = 0, sock_list[server->config->param.connections_max];
   SilcSocketConnection newsocket = NULL;
   SilcServerConfigServerInfoInterface *interface;
 
   for (interface = server->config->server_info->secondary; interface; 
        interface = interface->next, sock++) {
-         
+
     if (!silc_server_listen(server,
        interface->server_ip, interface->port, &sock_list[sock]))
       goto err;
@@ -150,9 +164,10 @@ bool silc_server_init_secondary(SilcServer server)
 
     /* Add ourselves also to the socket table. The entry allocated above
        is sent as argument for fast referencing in the future. */
-    silc_socket_alloc(sock_list[sock], 
-               SILC_SOCKET_TYPE_SERVER, NULL, &newsocket);
+    silc_socket_alloc(sock_list[sock],
+                     SILC_SOCKET_TYPE_SERVER, NULL, &newsocket);
     server->sockets[sock_list[sock]] = newsocket;
+    SILC_SET_LISTENER(newsocket);
 
     /* Perform name and address lookups to resolve the listenning address
        and port. */
@@ -170,23 +185,20 @@ bool silc_server_init_secondary(SilcServer server)
         newsocket->hostname = strdup(newsocket->ip);
     }
     newsocket->port = silc_net_get_local_port(sock);
-    
+
     newsocket->user_data = (void *)server->id_entry;
     silc_schedule_task_add(server->schedule, sock_list[sock],
                         silc_server_accept_new_connection,
                         (void *)server, 0, 0,
                         SILC_TASK_FD,
                         SILC_TASK_PRI_NORMAL);
-
   }
 
   return TRUE;
-  
-err:
 
+ err:
   do silc_net_close_server(sock_list[sock--]); while (sock >= 0);
   return FALSE;
-
 }
 
 /* Initializes the entire SILC server. This is called always before running
@@ -299,6 +311,7 @@ bool silc_server_init(SilcServer server)
      is sent as argument for fast referencing in the future. */
   silc_socket_alloc(sock, SILC_SOCKET_TYPE_SERVER, NULL, &newsocket);
   server->sockets[sock] = newsocket;
+  SILC_SET_LISTENER(newsocket);
 
   /* Perform name and address lookups to resolve the listenning address
      and port. */
@@ -325,7 +338,6 @@ bool silc_server_init(SilcServer server)
   server->id = id;
   server->id_string = silc_id_id2str(id, SILC_ID_SERVER);
   server->id_string_len = silc_id_get_len(id, SILC_ID_SERVER);
-  server->id_type = SILC_ID_SERVER;
   server->server_name = server->config->server_info->server_name;
   server->config->server_info->server_name = NULL;
 
@@ -396,7 +408,7 @@ bool silc_server_init(SilcServer server)
      and removes the expired cache entries. */
 
   /* Clients local list */
-  purge = silc_calloc(1, sizeof(*purge));
+  server->purge_i = purge = silc_calloc(1, sizeof(*purge));
   purge->cache = server->local_list->clients;
   purge->schedule = server->schedule;
   purge->timeout = 600;
@@ -406,7 +418,7 @@ bool silc_server_init(SilcServer server)
                         SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
 
   /* Clients global list */
-  purge = silc_calloc(1, sizeof(*purge));
+  server->purge_g = purge = silc_calloc(1, sizeof(*purge));
   purge->cache = server->global_list->clients;
   purge->schedule = server->schedule;
   purge->timeout = 300;
@@ -564,9 +576,33 @@ void silc_server_stop(SilcServer server)
   SILC_LOG_DEBUG(("Stopping server"));
 
   if (server->schedule) {
+    int i;
+
+    /* Close all connections */
+    for (i = 0; i < server->config->param.connections_max; i++) {
+      if (!server->sockets[i])
+       continue;
+      if (!SILC_IS_LISTENER(server->sockets[i])) {
+       silc_schedule_task_del_by_context(server->schedule,
+                                         server->sockets[i]);
+       silc_server_disconnect_remote(server, server->sockets[i], 
+                                     SILC_STATUS_OK, 
+                                     "Server is shutting down");
+      } else {
+       silc_socket_free(server->sockets[i]);
+       server->sockets[i] = NULL;
+      }
+    }
+
+    /* We are not connected to network anymore */
+    server->standalone = TRUE;
+
     silc_schedule_stop(server->schedule);
     silc_schedule_uninit(server->schedule);
     server->schedule = NULL;
+
+    silc_free(server->sockets);
+    server->sockets = NULL;
   }
 
   silc_server_protocols_unregister();
@@ -690,6 +726,9 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_retry)
     return;
   }
 
+  SILC_LOG_DEBUG(("Retrying connecting to a router in %d seconds",
+                 sconn->retry_timeout));
+
   /* We will lookup a fresh pointer later */
   silc_server_config_unref(&sconn->conn);
 
@@ -1111,11 +1150,11 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final)
       /* If we are router then announce our possible servers. */
       if (server->server_type == SILC_ROUTER)
        silc_server_announce_servers(server, FALSE, 0,
-                                    server->router->connection);
+                                    SILC_PRIMARY_ROUTE(server));
 
       /* Announce our clients and channels to the router */
-      silc_server_announce_clients(server, 0, server->router->connection);
-      silc_server_announce_channels(server, 0, server->router->connection);
+      silc_server_announce_clients(server, 0, SILC_PRIMARY_ROUTE(server));
+      silc_server_announce_channels(server, 0, SILC_PRIMARY_ROUTE(server));
 
 #ifdef BACKUP_SINGLE_ROUTER
       /* If we are backup router then this primary router is whom we are
@@ -1181,8 +1220,6 @@ silc_server_accept_new_connection_lookup(SilcSocketConnection sock,
 
   context = (void *)server;
 
-  SILC_LOG_DEBUG(("Start"));
-
   /* Check whether we could resolve both IP and FQDN. */
   if (!sock->ip || (!strcmp(sock->ip, sock->hostname) &&
                    server->config->require_reverse_lookup)) {
@@ -1209,6 +1246,14 @@ silc_server_accept_new_connection_lookup(SilcSocketConnection sock,
                 sock->ip));
 
   /* Listenning port */
+  if (!server->sockets[(SilcUInt32)proto_ctx->context]) {
+    silc_server_disconnect_remote(server, sock,
+                                 SILC_STATUS_ERR_RESOURCE_LIMIT,
+                                 "Connection refused");
+    server->stat.conn_failures++;
+    silc_free(proto_ctx);
+    return;
+  }
   port = server->sockets[(SilcUInt32)proto_ctx->context]->port;
 
   /* Check whether this connection is denied to connect to us. */
@@ -1275,6 +1320,7 @@ silc_server_accept_new_connection_lookup(SilcSocketConnection sock,
      initiator of the protocol thus we will wait for initiation from
      there before we start the protocol. */
   server->stat.auth_attempts++;
+  SILC_LOG_DEBUG(("Starting key exchange protocol"));
   silc_protocol_alloc(SILC_PROTOCOL_SERVER_KEY_EXCHANGE,
                      &sock->protocol, proto_ctx,
                      silc_server_accept_new_connection_second);
@@ -1360,6 +1406,7 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_second)
   if ((protocol->state == SILC_PROTOCOL_STATE_ERROR) ||
       (protocol->state == SILC_PROTOCOL_STATE_FAILURE)) {
     /* Error occured during protocol */
+    SILC_LOG_DEBUG(("Error key exchange protocol"));
     silc_protocol_free(protocol);
     sock->protocol = NULL;
     silc_ske_free_key_material(ctx->keymat);
@@ -1392,6 +1439,7 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_second)
                                        ctx->ske->prop->hmac,
                                        ctx->ske->prop->group,
                                        ctx->responder)) {
+    SILC_LOG_ERROR(("Error setting key material in use"));
     silc_protocol_free(protocol);
     sock->protocol = NULL;
     silc_ske_free_key_material(ctx->keymat);
@@ -1437,6 +1485,7 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_second)
      but we won't start it yet. We will be receiving party of this
      protocol thus we will wait that connecting party will make
      their first move. */
+  SILC_LOG_DEBUG(("Starting connection authentication protocol"));
   silc_protocol_alloc(SILC_PROTOCOL_SERVER_CONNECTION_AUTH,
                      &sock->protocol, proto_ctx,
                      silc_server_accept_new_connection_final);
@@ -1468,11 +1517,10 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
   void *id_entry;
   SilcUInt32 hearbeat_timeout = server->config->param.keepalive_secs;
 
-  SILC_LOG_DEBUG(("Start"));
-
   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
     /* Error occured during protocol */
+    SILC_LOG_DEBUG(("Error during authentication protocol"));
     silc_protocol_free(protocol);
     sock->protocol = NULL;
     if (ctx->packet)
@@ -1725,17 +1773,19 @@ SILC_TASK_CALLBACK(silc_server_packet_process)
   SilcUInt32 sequence = 0;
   int ret;
 
-  if (!sock)
+  if (!sock) {
+    SILC_LOG_DEBUG(("Unknown socket connection"));
     return;
-
-  SILC_LOG_DEBUG(("Processing packet"));
+  }
 
   /* Packet sending */
 
   if (type == SILC_TASK_WRITE) {
     /* Do not send data to disconnected connection */
-    if (SILC_IS_DISCONNECTED(sock))
+    if (SILC_IS_DISCONNECTED(sock)) {
+      SILC_LOG_DEBUG(("Disconnected socket connection, cannot send"));
       return;
+    }
 
     server->stat.packets_sent++;
 
@@ -1867,8 +1917,6 @@ SILC_TASK_CALLBACK(silc_server_packet_parse_real)
   SilcIDListData idata = (SilcIDListData)sock->user_data;
   int ret;
 
-  SILC_LOG_DEBUG(("Start"));
-
   /* Parse the packet */
   if (parse_ctx->normal)
     ret = silc_packet_parse(packet, idata ? idata->receive_key : NULL);
@@ -1882,8 +1930,10 @@ SILC_TASK_CALLBACK(silc_server_packet_parse_real)
     goto out;
   }
 
-  if (ret == SILC_PACKET_NONE)
+  if (ret == SILC_PACKET_NONE) {
+    SILC_LOG_DEBUG(("Error parsing packet"));
     goto out;
+  }
 
   /* Check that the the current client ID is same as in the client's packet. */
   if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
@@ -1893,6 +1943,7 @@ SILC_TASK_CALLBACK(silc_server_packet_parse_real)
                                packet->src_id_type);
       if (!id || !SILC_ID_CLIENT_COMPARE(client->id, id)) {
        silc_free(id);
+       SILC_LOG_DEBUG(("Packet source is not same as sender"));
        goto out;
       }
       silc_free(id);
@@ -1924,19 +1975,17 @@ SILC_TASK_CALLBACK(silc_server_packet_parse_real)
   /* Parse the incoming packet type */
   silc_server_packet_parse_type(server, sock, packet);
 
-  if (server->server_type == SILC_ROUTER) {
-    /* Broadcast packet if it is marked as broadcast packet and it is
-       originated from router and we are router. */
-    if (sock->type == SILC_SOCKET_TYPE_ROUTER &&
-       packet->flags & SILC_PACKET_FLAG_BROADCAST &&
-       !server->standalone) {
-      /* Broadcast to our primary route */
-      silc_server_packet_broadcast(server, server->router->connection, packet);
-
-      /* If we have backup routers then we need to feed all broadcast
-        data to those servers. */
-      silc_server_backup_broadcast(server, sock, packet);
-    }
+  /* Broadcast packet if it is marked as broadcast packet and it is
+     originated from router and we are router. */
+  if (server->server_type == SILC_ROUTER &&
+      sock->type == SILC_SOCKET_TYPE_ROUTER &&
+      packet->flags & SILC_PACKET_FLAG_BROADCAST) {
+    /* Broadcast to our primary route */
+    silc_server_packet_broadcast(server, SILC_PRIMARY_ROUTE(server), packet);
+
+    /* If we have backup routers then we need to feed all broadcast
+       data to those servers. */
+    silc_server_backup_broadcast(server, sock, packet);
   }
 
  out:
@@ -2017,7 +2066,8 @@ void silc_server_packet_parse_type(SilcServer server,
   SilcPacketType type = packet->type;
   SilcIDListData idata = (SilcIDListData)sock->user_data;
 
-  SILC_LOG_DEBUG(("Parsing packet type %d", type));
+  SILC_LOG_DEBUG(("Received %s packet [flags %d]",
+                 silc_get_packet_name(type), packet->flags));
 
   /* Parse the packet type */
   switch (type) {
@@ -2026,8 +2076,6 @@ void silc_server_packet_parse_type(SilcServer server,
       SilcStatus status;
       char *message = NULL;
 
-      SILC_LOG_DEBUG(("Disconnect packet"));
-
       if (packet->flags & SILC_PACKET_FLAG_LIST)
        break;
       if (packet->buffer->len < 1)
@@ -2036,7 +2084,8 @@ void silc_server_packet_parse_type(SilcServer server,
       status = (SilcStatus)packet->buffer->data[0];
       if (packet->buffer->len > 1 &&
          silc_utf8_valid(packet->buffer->data + 1, packet->buffer->len - 1))
-       message = silc_memdup(packet->buffer->data, packet->buffer->len);
+       message = silc_memdup(packet->buffer->data + 1,
+                             packet->buffer->len - 1);
 
       SILC_LOG_ERROR(("Disconnected by %s (%s): %s (%d) %s", 
                      sock->ip, sock->hostname,
@@ -2052,7 +2101,6 @@ void silc_server_packet_parse_type(SilcServer server,
      * one protocol for connection executing at once hence this
      * success message is for whatever protocol is executing currently.
      */
-    SILC_LOG_DEBUG(("Success packet"));
     if (packet->flags & SILC_PACKET_FLAG_LIST)
       break;
     if (sock->protocol)
@@ -2065,7 +2113,6 @@ void silc_server_packet_parse_type(SilcServer server,
      * one protocol for connection executing at once hence this
      * failure message is for whatever protocol is executing currently.
      */
-    SILC_LOG_DEBUG(("Failure packet"));
     if (packet->flags & SILC_PACKET_FLAG_LIST)
       break;
     if (sock->protocol) {
@@ -2082,7 +2129,6 @@ void silc_server_packet_parse_type(SilcServer server,
     break;
 
   case SILC_PACKET_REJECT:
-    SILC_LOG_DEBUG(("Reject packet"));
     if (packet->flags & SILC_PACKET_FLAG_LIST)
       break;
     return;
@@ -2093,7 +2139,6 @@ void silc_server_packet_parse_type(SilcServer server,
      * Received notify packet. Server can receive notify packets from
      * router. Server then relays the notify messages to clients if needed.
      */
-    SILC_LOG_DEBUG(("Notify packet"));
     if (packet->flags & SILC_PACKET_FLAG_LIST)
       silc_server_notify_list(server, sock, packet);
     else
@@ -2109,7 +2154,6 @@ void silc_server_packet_parse_type(SilcServer server,
      * (although probably most common ones) thus they are handled
      * specially.
      */
-    SILC_LOG_DEBUG(("Channel Message packet"));
     if (packet->flags & SILC_PACKET_FLAG_LIST)
       break;
     idata->last_receive = time(NULL);
@@ -2123,7 +2167,6 @@ void silc_server_packet_parse_type(SilcServer server,
      * locally connected clients on the particular channel. Router
      * never receives this channel and thus is ignored.
      */
-    SILC_LOG_DEBUG(("Channel Key packet"));
     if (packet->flags & SILC_PACKET_FLAG_LIST)
       break;
     silc_server_channel_key(server, sock, packet);
@@ -2137,7 +2180,6 @@ void silc_server_packet_parse_type(SilcServer server,
      * Recived command. Processes the command request and allocates the
      * command context and calls the command.
      */
-    SILC_LOG_DEBUG(("Command packet"));
     if (packet->flags & SILC_PACKET_FLAG_LIST)
       break;
     silc_server_command_process(server, sock, packet);
@@ -2149,7 +2191,6 @@ void silc_server_packet_parse_type(SilcServer server,
      * may be reply to command sent by us or reply to command sent by client
      * that we've routed further.
      */
-    SILC_LOG_DEBUG(("Command Reply packet"));
     if (packet->flags & SILC_PACKET_FLAG_LIST)
       break;
     silc_server_command_reply(server, sock, packet);
@@ -2163,7 +2204,6 @@ void silc_server_packet_parse_type(SilcServer server,
      * Received private message packet. The packet is coming from either
      * client or server.
      */
-    SILC_LOG_DEBUG(("Private Message packet"));
     if (packet->flags & SILC_PACKET_FLAG_LIST)
       break;
     idata->last_receive = time(NULL);
@@ -2183,7 +2223,6 @@ void silc_server_packet_parse_type(SilcServer server,
      * Key Exchange protocol packets
      */
   case SILC_PACKET_KEY_EXCHANGE:
-    SILC_LOG_DEBUG(("KE packet"));
     if (packet->flags & SILC_PACKET_FLAG_LIST)
       break;
 
@@ -2203,7 +2242,6 @@ void silc_server_packet_parse_type(SilcServer server,
     break;
 
   case SILC_PACKET_KEY_EXCHANGE_1:
-    SILC_LOG_DEBUG(("KE 1 packet"));
     if (packet->flags & SILC_PACKET_FLAG_LIST)
       break;
 
@@ -2247,7 +2285,6 @@ void silc_server_packet_parse_type(SilcServer server,
     break;
 
   case SILC_PACKET_KEY_EXCHANGE_2:
-    SILC_LOG_DEBUG(("KE 2 packet"));
     if (packet->flags & SILC_PACKET_FLAG_LIST)
       break;
 
@@ -2297,7 +2334,6 @@ void silc_server_packet_parse_type(SilcServer server,
      * authentication method for the connection. This packet maybe received
      * at any time.
      */
-    SILC_LOG_DEBUG(("Connection authentication request packet"));
     if (packet->flags & SILC_PACKET_FLAG_LIST)
       break;
     silc_server_connection_auth_request(server, sock, packet);
@@ -2309,7 +2345,6 @@ void silc_server_packet_parse_type(SilcServer server,
   case SILC_PACKET_CONNECTION_AUTH:
     /* Start of the authentication protocol. We receive here the
        authentication data and will verify it. */
-    SILC_LOG_DEBUG(("Connection auth packet"));
     if (packet->flags & SILC_PACKET_FLAG_LIST)
       break;
 
@@ -2336,7 +2371,6 @@ void silc_server_packet_parse_type(SilcServer server,
      * to distribute information about new registered entities in the
      * SILC network.
      */
-    SILC_LOG_DEBUG(("New ID packet"));
     if (packet->flags & SILC_PACKET_FLAG_LIST)
       silc_server_new_id_list(server, sock, packet);
     else
@@ -2349,7 +2383,6 @@ void silc_server_packet_parse_type(SilcServer server,
      * we will use to create initial client ID. After creating new
      * ID we will send it to the client.
      */
-    SILC_LOG_DEBUG(("New Client packet"));
     if (packet->flags & SILC_PACKET_FLAG_LIST)
       break;
     silc_server_new_client(server, sock, packet);
@@ -2361,7 +2394,6 @@ void silc_server_packet_parse_type(SilcServer server,
      * information that we may save. This is received after server has
      * connected to us.
      */
-    SILC_LOG_DEBUG(("New Server packet"));
     if (packet->flags & SILC_PACKET_FLAG_LIST)
       break;
     silc_server_new_server(server, sock, packet);
@@ -2372,7 +2404,6 @@ void silc_server_packet_parse_type(SilcServer server,
      * Received new channel packet. Information about new channel in the
      * network are distributed using this packet.
      */
-    SILC_LOG_DEBUG(("New Channel packet"));
     if (packet->flags & SILC_PACKET_FLAG_LIST)
       silc_server_new_channel_list(server, sock, packet);
     else
@@ -2383,7 +2414,6 @@ void silc_server_packet_parse_type(SilcServer server,
     /*
      * Received heartbeat.
      */
-    SILC_LOG_DEBUG(("Heartbeat packet"));
     if (packet->flags & SILC_PACKET_FLAG_LIST)
       break;
     break;
@@ -2392,7 +2422,6 @@ void silc_server_packet_parse_type(SilcServer server,
     /*
      * Received heartbeat.
      */
-    SILC_LOG_DEBUG(("Key agreement packet"));
     if (packet->flags & SILC_PACKET_FLAG_LIST)
       break;
     silc_server_key_agreement(server, sock, packet);
@@ -2403,7 +2432,6 @@ void silc_server_packet_parse_type(SilcServer server,
      * Received re-key packet. The sender wants to regenerate the session
      * keys.
      */
-    SILC_LOG_DEBUG(("Re-key packet"));
     if (packet->flags & SILC_PACKET_FLAG_LIST)
       break;
     silc_server_rekey(server, sock, packet);
@@ -2413,7 +2441,6 @@ void silc_server_packet_parse_type(SilcServer server,
     /*
      * The re-key is done.
      */
-    SILC_LOG_DEBUG(("Re-key done packet"));
     if (packet->flags & SILC_PACKET_FLAG_LIST)
       break;
 
@@ -2438,7 +2465,6 @@ void silc_server_packet_parse_type(SilcServer server,
 
   case SILC_PACKET_FTP:
     /* FTP packet */
-    SILC_LOG_DEBUG(("FTP packet"));
     if (packet->flags & SILC_PACKET_FLAG_LIST)
       break;
     silc_server_ftp(server, sock, packet);
@@ -2446,7 +2472,6 @@ void silc_server_packet_parse_type(SilcServer server,
 
   case SILC_PACKET_RESUME_CLIENT:
     /* Resume client */
-    SILC_LOG_DEBUG(("Resume Client packet"));
     if (packet->flags & SILC_PACKET_FLAG_LIST)
       break;
     silc_server_resume_client(server, sock, packet);
@@ -2455,7 +2480,6 @@ void silc_server_packet_parse_type(SilcServer server,
   case SILC_PACKET_RESUME_ROUTER:
     /* Resume router packet received. This packet is received for backup
        router resuming protocol. */
-    SILC_LOG_DEBUG(("Resume router packet"));
     if (packet->flags & SILC_PACKET_FLAG_LIST)
       break;
     silc_server_backup_resume_router(server, sock, packet);
@@ -2465,7 +2489,6 @@ void silc_server_packet_parse_type(SilcServer server,
     SILC_LOG_ERROR(("Incorrect packet type %d, packet dropped", type));
     break;
   }
-
 }
 
 /* Creates connection to a remote router. */
@@ -2498,8 +2521,10 @@ SILC_TASK_CALLBACK(silc_server_close_connection_final)
 void silc_server_close_connection(SilcServer server,
                                  SilcSocketConnection sock)
 {
-  if (!server->sockets[sock->sock])
+  if (!server->sockets[sock->sock] && SILC_IS_DISCONNECTED(sock)) {
+    silc_socket_free(sock);
     return;
+  }
 
   SILC_LOG_INFO(("Closing connection %s:%d [%s]", sock->hostname,
                   sock->port,
@@ -2525,6 +2550,7 @@ void silc_server_close_connection(SilcServer server,
     /* If any protocol is active cancel its execution. It will call
        the final callback which will finalize the disconnection. */
     if (sock->protocol) {
+      SILC_LOG_DEBUG(("Cancelling protocol, calling final callback"));
       silc_protocol_cancel(sock->protocol, server->schedule);
       sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
       silc_protocol_execute_final(sock->protocol, server->schedule);
@@ -2617,6 +2643,18 @@ void silc_server_free_client_data(SilcServer server,
 {
   FreeClientInternal i = silc_calloc(1, sizeof(*i));
 
+  SILC_LOG_DEBUG(("Freeing client data"));
+
+#if 1
+  if (!client->router && !client->connection &&
+      !(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
+    SILC_LOG_ERROR(("****** freeing data for already unregistered client -s"));
+    SILC_LOG_ERROR(("****** Contact Pekka"));
+    SILC_LOG_ERROR(("****** freeing data for already unregistered client -e"));
+    return;
+  }
+#endif
+
   /* If there is pending outgoing data for the client then purge it
      to the network before removing the client entry. */
   silc_server_packet_queue_purge(server, sock);
@@ -2628,23 +2666,23 @@ void silc_server_free_client_data(SilcServer server,
                                     SILC_NOTIFY_TYPE_SIGNOFF);
 
     /* Send SIGNOFF notify to routers. */
-    if (notify && !server->standalone && server->router)
-      silc_server_send_notify_signoff(server, server->router->connection,
-                                     server->server_type == SILC_SERVER ?
-                                     FALSE : TRUE, client->id, signoff);
-
-    /* Remove client from all channels */
     if (notify)
-      silc_server_remove_from_channels(server, NULL, client,
-                                      TRUE, (char *)signoff, TRUE);
-    else
-      silc_server_remove_from_channels(server, NULL, client,
-                                      FALSE, NULL, FALSE);
-
-    /* Remove this client from watcher list if it is */
-    silc_server_del_from_watcher_list(server, client);
+      silc_server_send_notify_signoff(server, SILC_PRIMARY_ROUTE(server),
+                                     SILC_BROADCAST(server), client->id,
+                                     signoff);
   }
 
+  /* Remove client from all channels */
+  if (notify)
+    silc_server_remove_from_channels(server, NULL, client,
+                                    TRUE, (char *)signoff, TRUE);
+  else
+    silc_server_remove_from_channels(server, NULL, client,
+                                    FALSE, NULL, FALSE);
+
+  /* Remove this client from watcher list if it is */
+  silc_server_del_from_watcher_list(server, client);
+
   /* Update statistics */
   server->stat.my_clients--;
   server->stat.clients--;
@@ -2676,8 +2714,6 @@ void silc_server_free_sock_user_data(SilcServer server,
                                     SilcSocketConnection sock,
                                     const char *signoff_message)
 {
-  SILC_LOG_DEBUG(("Start"));
-
   switch (sock->type) {
   case SILC_SOCKET_TYPE_CLIENT:
     {
@@ -2692,6 +2728,8 @@ void silc_server_free_sock_user_data(SilcServer server,
       SilcServerEntry user_data = (SilcServerEntry)sock->user_data;
       SilcServerEntry backup_router = NULL;
 
+      SILC_LOG_DEBUG(("Freeing server data"));
+
       if (user_data->id)
        backup_router = silc_server_backup_get(server, user_data->id);
 
@@ -2809,6 +2847,8 @@ void silc_server_free_sock_user_data(SilcServer server,
     {
       SilcUnknownEntry user_data = (SilcUnknownEntry)sock->user_data;
 
+      SILC_LOG_DEBUG(("Freeing unknown connection data"));
+
       silc_idlist_del_data(user_data);
       silc_free(user_data);
       break;
@@ -2817,6 +2857,7 @@ void silc_server_free_sock_user_data(SilcServer server,
 
   /* If any protocol is active cancel its execution */
   if (sock->protocol) {
+    SILC_LOG_DEBUG(("Cancelling protocol, calling final callback"));
     silc_protocol_cancel(sock->protocol, server->schedule);
     sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
     silc_protocol_execute_final(sock->protocol, server->schedule);
@@ -2840,17 +2881,22 @@ void silc_server_remove_from_channels(SilcServer server,
   SilcChannelEntry channel;
   SilcChannelClientEntry chl;
   SilcHashTableList htl;
-  SilcBuffer clidp;
-
-  SILC_LOG_DEBUG(("Start"));
+  SilcBuffer clidp = NULL;
 
-  if (!client || !client->id)
+  if (!client)
     return;
 
-  clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
-  if (!clidp)
+  SILC_LOG_DEBUG(("Removing client from joined channels"));
+
+  if (notify && !client->id)
     notify = FALSE;
 
+  if (notify) {
+    clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
+    if (!clidp)
+      notify = FALSE;
+  }
+
   /* Remove the client from all channels. The client is removed from
      the channels' user list. */
   silc_hash_table_list(client->channels, &htl);
@@ -2876,7 +2922,14 @@ void silc_server_remove_from_channels(SilcServer server,
       channel->global_users = FALSE;
 
     silc_free(chl);
-    server->stat.my_chanclients--;
+
+    /* Update statistics */
+    if (client->connection)
+      server->stat.my_chanclients--;
+    if (server->server_type == SILC_ROUTER) {
+      server->stat.cell_chanclients--;
+      server->stat.chanclients--;
+    }
 
     /* If there is not at least one local user on the channel then we don't
        need the channel entry anymore, we can remove it safely, unless the
@@ -2920,7 +2973,8 @@ void silc_server_remove_from_channels(SilcServer server,
   }
 
   silc_hash_table_list_reset(&htl);
-  silc_buffer_free(clidp);
+  if (clidp)
+    silc_buffer_free(clidp);
 }
 
 /* Removes client from one channel. This is used for example when client
@@ -2966,7 +3020,14 @@ bool silc_server_remove_from_one_channel(SilcServer server,
     channel->global_users = FALSE;
 
   silc_free(chl);
-  server->stat.my_chanclients--;
+
+  /* Update statistics */
+  if (client->connection)
+    server->stat.my_chanclients--;
+  if (server->server_type == SILC_ROUTER) {
+    server->stat.cell_chanclients--;
+    server->stat.chanclients--;
+  }
 
   clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
   if (!clidp)
@@ -3056,7 +3117,7 @@ SilcChannelEntry silc_server_create_new_channel(SilcServer server,
   SilcCipher key;
   SilcHmac newhmac;
 
-  SILC_LOG_DEBUG(("Creating new channel"));
+  SILC_LOG_DEBUG(("Creating new channel %s", channel_name));
 
   if (!cipher)
     cipher = SILC_DEFAULT_CIPHER;
@@ -3108,8 +3169,8 @@ SilcChannelEntry silc_server_create_new_channel(SilcServer server,
 
   /* Notify other routers about the new channel. We send the packet
      to our primary route. */
-  if (broadcast && server->standalone == FALSE)
-    silc_server_send_new_channel(server, server->router->connection, TRUE,
+  if (broadcast)
+    silc_server_send_new_channel(server, SILC_PRIMARY_ROUTE(server), TRUE,
                                 channel_name, entry->id,
                                 silc_id_get_len(entry->id, SILC_ID_CHANNEL),
                                 entry->mode);
@@ -3131,9 +3192,11 @@ SilcChannelEntry silc_server_create_new_channel(SilcServer server,
   }
 
   server->stat.my_channels++;
-
-  if (server->server_type == SILC_ROUTER)
+  if (server->server_type == SILC_ROUTER) {
+    server->stat.channels++;
+    server->stat.cell_channels++;
     entry->users_resolved = TRUE;
+  }
 
   return entry;
 }
@@ -3152,7 +3215,7 @@ silc_server_create_new_channel_with_id(SilcServer server,
   SilcCipher key;
   SilcHmac newhmac;
 
-  SILC_LOG_DEBUG(("Creating new channel"));
+  SILC_LOG_DEBUG(("Creating new channel %s", channel_name));
 
   if (!cipher)
     cipher = SILC_DEFAULT_CIPHER;
@@ -3191,8 +3254,8 @@ silc_server_create_new_channel_with_id(SilcServer server,
 
   /* Notify other routers about the new channel. We send the packet
      to our primary route. */
-  if (broadcast && server->standalone == FALSE)
-    silc_server_send_new_channel(server, server->router->connection, TRUE,
+  if (broadcast)
+    silc_server_send_new_channel(server, SILC_PRIMARY_ROUTE(server), TRUE,
                                 channel_name, entry->id,
                                 silc_id_get_len(entry->id, SILC_ID_CHANNEL),
                                 entry->mode);
@@ -3214,9 +3277,11 @@ silc_server_create_new_channel_with_id(SilcServer server,
   }
 
   server->stat.my_channels++;
-
-  if (server->server_type == SILC_ROUTER)
+  if (server->server_type == SILC_ROUTER) {
+    server->stat.channels++;
+    server->stat.cell_channels++;
     entry->users_resolved = TRUE;
+  }
 
   return entry;
 }
@@ -3328,7 +3393,7 @@ SilcChannelEntry silc_server_save_channel_key(SilcServer server,
   SilcUInt32 tmp_len;
   char *cipher;
 
-  SILC_LOG_DEBUG(("Start"));
+  SILC_LOG_DEBUG(("Saving new channel key"));
 
   /* Decode channel key payload */
   payload = silc_channel_key_payload_parse(key_payload->data,
@@ -4351,7 +4416,7 @@ silc_server_get_client_route(SilcServer server,
     silc_free(id);
     if (idata)
       *idata = (SilcIDListData)server->router;
-    return server->router->connection;
+    return SILC_PRIMARY_ROUTE(server);
   }
 
   /* We are router and we will perform route lookup for the destination
@@ -4487,7 +4552,7 @@ SilcClientEntry silc_server_get_client_resolve(SilcServer server,
                                            server->cmd_ident, 1,
                                            4, idp->data, idp->len);
     silc_server_packet_send(server, client ? client->router->connection :
-                           server->router->connection,
+                           SILC_PRIMARY_ROUTE(server),
                            SILC_PACKET_COMMAND, 0,
                            buffer->data, buffer->len, FALSE);
     silc_buffer_free(idp);
@@ -4596,7 +4661,7 @@ SILC_TASK_CALLBACK(silc_server_get_stats)
     packet = silc_command_payload_encode_va(SILC_COMMAND_STATS, 
                                            ++server->cmd_ident, 1,
                                            1, idp->data, idp->len);
-    silc_server_packet_send(server, server->router->connection,
+    silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
                            SILC_PACKET_COMMAND, 0, packet->data,
                            packet->len, FALSE);
     silc_buffer_free(packet);