Fixed KILL command related crash in silcd
[runtime.git] / apps / silcd / server.c
index 46fccfc085d68ca3bb47b682dd69c7026be39a14..7453f5f5d1bcb8c832aefaebf41b5d6da0ddb1d2 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2007 Pekka Riikonen
+  Copyright (C) 1997 - 2008 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -103,12 +103,13 @@ static SilcBool silc_server_packet_receive(SilcPacketEngine engine,
        !(idata->status & SILC_IDLIST_STATUS_REGISTERED)) &&
       packet->type != SILC_PACKET_NEW_CLIENT &&
       packet->type != SILC_PACKET_NEW_SERVER &&
+      packet->type != SILC_PACKET_RESUME_CLIENT &&
       packet->type != SILC_PACKET_CONNECTION_AUTH_REQUEST &&
       packet->type != SILC_PACKET_DISCONNECT)
     return FALSE;
 
-  /* NEW_CLIENT and NEW_SERVER are accepted only without source ID
-     and for unregistered connection. */
+  /* NEW_CLIENT and NEW_SERVER are accepted only without source ID and
+     for unregistered connection. */
   if (packet->src_id && (packet->type == SILC_PACKET_NEW_CLIENT ||
                         packet->type == SILC_PACKET_NEW_SERVER) &&
       (idata->status & SILC_IDLIST_STATUS_REGISTERED))
@@ -130,7 +131,8 @@ static SilcBool silc_server_packet_receive(SilcPacketEngine engine,
        silc_id_str2id(packet->src_id, packet->src_id_len,
                       packet->src_id_type, &client_id, sizeof(client_id))) {
       if (!SILC_ID_CLIENT_COMPARE(client->id, &client_id)) {
-       SILC_LOG_DEBUG(("Packet source is not same as sender"));
+       SILC_LOG_DEBUG(("Packet source is not same as sender, packet %s",
+                       silc_get_packet_name(packet->type)));
        return FALSE;
       }
     }
@@ -200,6 +202,7 @@ static void silc_server_packet_eos(SilcPacketEngine engine,
   if (server->router_conn && server->router_conn->sock == stream &&
       !server->router && server->standalone) {
     silc_server_create_connections(server);
+    silc_server_free_sock_user_data(server, stream, NULL);
   } else {
     /* If backup disconnected then mark that resuming will not be allowed */
      if (server->server_type == SILC_ROUTER && !server->backup_router &&
@@ -266,6 +269,9 @@ static void silc_server_packet_error(SilcPacketEngine engine,
                  SILC_CONNTYPE_STRING(idata->conn_type),
                  silc_packet_error_string(error)));
 
+  if (!silc_packet_stream_is_valid(stream))
+    return;
+
   silc_schedule_task_add_timeout(server->schedule,
                                 silc_server_packet_error_timeout,
                                 stream, 0, 0);
@@ -666,6 +672,10 @@ void silc_server_free(SilcServer server)
     }
   }
 
+  silc_schedule_task_del_by_context(server->schedule, server);
+  silc_schedule_uninit(server->schedule);
+  server->schedule = NULL;
+
   silc_idcache_free(server->local_list->clients);
   silc_idcache_free(server->local_list->servers);
   silc_idcache_free(server->local_list->channels);
@@ -683,10 +693,6 @@ void silc_server_free(SilcServer server)
   silc_skr_free(server->repository);
   silc_packet_engine_stop(server->packet_engine);
 
-  silc_schedule_task_del_by_context(server->schedule, server);
-  silc_schedule_uninit(server->schedule);
-  server->schedule = NULL;
-
   silc_free(server->local_list);
   silc_free(server->global_list);
   silc_free(server->server_name);
@@ -915,15 +921,19 @@ SilcBool silc_server_init(SilcServer server)
     }
   }
 
+  if (server->server_type != SILC_ROUTER) {
+    server->stat.servers = 1;
+    server->stat.cell_servers = 1;
+  } else {
+    server->stat.routers = 1;
+  }
+
   /* If we are normal server we'll retrieve network statisticial information
      once in a while from the router. */
   if (server->server_type != SILC_ROUTER)
     silc_schedule_task_add_timeout(server->schedule, silc_server_get_stats,
                                   server, 10, 0);
 
-  if (server->server_type == SILC_ROUTER)
-    server->stat.routers++;
-
   /* Start packet engine */
   server->packet_engine =
     silc_packet_engine_start(server->rng, server->server_type == SILC_ROUTER,
@@ -1202,6 +1212,9 @@ void silc_server_stop(SilcServer server)
     while ((ps = silc_dlist_get(list))) {
       SilcIDListData idata = silc_packet_get_context(ps);
 
+      if (!silc_packet_stream_is_valid(ps))
+       continue;
+
       if (idata)
        idata->status &= ~SILC_IDLIST_STATUS_DISABLED;
 
@@ -1227,6 +1240,8 @@ void silc_server_stop(SilcServer server)
                                     silc_server_connect_router);
   silc_schedule_task_del_by_callback(server->schedule,
                                     silc_server_connect_to_router_retry);
+  silc_schedule_task_del_by_callback(server->schedule,
+                                    silc_server_connect_to_router);
 
   silc_schedule_stop(server->schedule);
 
@@ -1330,9 +1345,9 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success,
   SilcID remote_id;
   const char *ip;
 
-  SILC_LOG_DEBUG(("Connection authentication completed"));
+  SILC_LOG_DEBUG(("Connection %p authentication completed", sconn));
 
-  sconn->op = NULL;
+  entry->op = NULL;
 
   if (success == FALSE) {
     /* Authentication failed */
@@ -1342,6 +1357,7 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success,
                                  SILC_STATUS_ERR_AUTH_FAILED, NULL);
     if (sconn->callback)
       (*sconn->callback)(server, NULL, sconn->callback_context);
+    silc_server_free_sock_user_data(server, sconn->sock, NULL);
     silc_server_connection_free(sconn);
     return;
   }
@@ -1368,11 +1384,18 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success,
                                    SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
       if (sconn->callback)
        (*sconn->callback)(server, NULL, sconn->callback_context);
+      silc_server_free_sock_user_data(server, sconn->sock, NULL);
       silc_server_connection_free(sconn);
       silc_free(entry);
       return;
     }
 
+    /* Statistics */
+    server->stat.my_servers++;
+    if (server->server_type == SILC_ROUTER)
+      server->stat.servers++;
+    SILC_LOG_DEBUG(("my_servers %d", server->stat.my_servers));
+
     silc_idlist_add_data(id_entry, (SilcIDListData)entry);
     break;
 
@@ -1392,6 +1415,7 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success,
                                    SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
       if (sconn->callback)
        (*sconn->callback)(server, NULL, sconn->callback_context);
+      silc_server_free_sock_user_data(server, sconn->sock, NULL);
       silc_server_connection_free(sconn);
       silc_free(entry);
       return;
@@ -1431,6 +1455,7 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success,
                                    SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
       if (sconn->callback)
        (*sconn->callback)(server, NULL, sconn->callback_context);
+      silc_server_free_sock_user_data(server, sconn->sock, NULL);
       silc_server_connection_free(sconn);
       silc_free(entry);
       return;
@@ -1443,6 +1468,12 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success,
                      SILC_IDLIST_STATUS_LOCAL);
     idata->sconn = sconn;
 
+    /* Statistics */
+    server->stat.my_routers++;
+    if (server->server_type == SILC_ROUTER)
+      server->stat.routers++;
+    SILC_LOG_DEBUG(("my_routers %d", server->stat.my_routers));
+
     if (!sconn->backup) {
       /* Mark this router our primary router if we're still standalone */
       if (server->standalone) {
@@ -1508,6 +1539,7 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success,
                                  SILC_STATUS_ERR_AUTH_FAILED, NULL);
     if (sconn->callback)
       (*sconn->callback)(server, NULL, sconn->callback_context);
+    silc_server_free_sock_user_data(server, sconn->sock, NULL);
     silc_server_connection_free(sconn);
     silc_free(entry);
     return;
@@ -1528,7 +1560,6 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success,
   /* Set the entry as packet stream context */
   silc_packet_set_context(sconn->sock, id_entry);
 
- out:
   /* Call the completion callback to indicate that we've connected to
      the router */
   if (sconn && sconn->callback)
@@ -1561,7 +1592,9 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status,
   SilcHmac hmac_send, hmac_receive;
   SilcHash hash;
 
-  sconn->op = NULL;
+  SILC_LOG_DEBUG(("Connection %p, SKE completed", sconn));
+
+  entry->op = NULL;
 
   if (status != SILC_SKE_STATUS_OK) {
     /* SKE failed */
@@ -1574,6 +1607,7 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status,
                                  SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
     if (sconn->callback)
       (*sconn->callback)(server, NULL, sconn->callback_context);
+    silc_server_free_sock_user_data(server, sconn->sock, NULL);
     silc_server_connection_free(sconn);
     return;
   }
@@ -1592,6 +1626,7 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status,
                                  SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
     if (sconn->callback)
       (*sconn->callback)(server, NULL, sconn->callback_context);
+    silc_server_free_sock_user_data(server, sconn->sock, NULL);
     silc_server_connection_free(sconn);
     return;
   }
@@ -1611,6 +1646,7 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status,
                                  SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
     if (sconn->callback)
       (*sconn->callback)(server, NULL, sconn->callback_context);
+    silc_server_free_sock_user_data(server, sconn->sock, NULL);
     silc_server_connection_free(sconn);
     return;
   }
@@ -1635,7 +1671,7 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status,
   entry->data.rekey = rekey;
 
   /* Start connection authentication */
-  sconn->op =
+  entry->op =
     silc_connauth_initiator(connauth, server->server_type == SILC_SERVER ?
                            SILC_CONN_SERVER : SILC_CONN_ROUTER, auth_meth,
                            auth_data, auth_data_len,
@@ -1698,7 +1734,7 @@ void silc_server_start_key_exchange(SilcServerConnection sconn)
     params.flags |= SILC_SKE_SP_FLAG_PFS;
 
   /* Start SILC Key Exchange protocol */
-  SILC_LOG_DEBUG(("Starting key exchange protocol"));
+  SILC_LOG_DEBUG(("Starting key exchange protocol, connection %p", sconn));
   ske = silc_ske_alloc(server->rng, server->schedule, server->repository,
                       server->public_key, server->private_key, sconn);
   if (!ske) {
@@ -1715,7 +1751,7 @@ void silc_server_start_key_exchange(SilcServerConnection sconn)
   /* Start key exchange protocol */
   params.version = silc_version_string;
   params.timeout_secs = server->config->key_exchange_timeout;
-  sconn->op = silc_ske_initiator(ske, sconn->sock, &params, NULL);
+  entry->op = silc_ske_initiator(ske, sconn->sock, &params, NULL);
 }
 
 /* Timeout callback that will be called to retry connecting to remote
@@ -1782,7 +1818,7 @@ static void silc_server_connection_established(SilcNetStatus status,
 
   switch (status) {
   case SILC_NET_OK:
-    SILC_LOG_DEBUG(("Connection to %s:%d established",
+    SILC_LOG_DEBUG(("Connection %p to %s:%d established", sconn,
                    sconn->remote_host, sconn->remote_port));
 
     /* Continue with key exchange protocol */
@@ -2022,7 +2058,16 @@ silc_server_accept_get_auth(SilcConnAuth connauth,
     if (cconfig->publickeys)
       *repository = server->repository;
 
-    entry->data.conn_type = conn_type;
+    if (cconfig->publickeys) {
+      if (server->config->prefer_passphrase_auth) {
+       *repository = NULL;
+      } else {
+       *passphrase = NULL;
+       *passphrase_len = 0;
+      }
+    }
+
+    entry->conn_type = conn_type;
     return TRUE;
   }
 
@@ -2043,7 +2088,16 @@ silc_server_accept_get_auth(SilcConnAuth connauth,
     if (sconfig->publickeys)
       *repository = server->repository;
 
-    entry->data.conn_type = conn_type;
+    if (sconfig->publickeys) {
+      if (server->config->prefer_passphrase_auth) {
+       *repository = NULL;
+      } else {
+       *passphrase = NULL;
+       *passphrase_len = 0;
+      }
+    }
+
+    entry->conn_type = conn_type;
     return TRUE;
   }
 
@@ -2058,7 +2112,16 @@ silc_server_accept_get_auth(SilcConnAuth connauth,
     if (rconfig->publickeys)
       *repository = server->repository;
 
-    entry->data.conn_type = conn_type;
+    if (rconfig->publickeys) {
+      if (server->config->prefer_passphrase_auth) {
+       *repository = NULL;
+      } else {
+       *passphrase = NULL;
+       *passphrase_len = 0;
+      }
+    }
+
+    entry->conn_type = conn_type;
     return TRUE;
   }
 
@@ -2092,19 +2155,20 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success,
     server->stat.auth_failures++;
     silc_server_disconnect_remote(server, sock,
                                  SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
+    silc_server_free_sock_user_data(server, sock, NULL);
     goto out;
   }
 
   SILC_LOG_DEBUG(("Checking whether connection is allowed"));
 
-  switch (entry->data.conn_type) {
+  switch (entry->conn_type) {
   case SILC_CONN_CLIENT:
     {
       SilcClientEntry client;
       SilcServerConfigClient *conn = entry->cconfig.ref_ptr;
 
       /* Verify whether this connection is after all allowed to connect */
-      if (!silc_server_connection_allowed(server, sock, entry->data.conn_type,
+      if (!silc_server_connection_allowed(server, sock, entry->conn_type,
                                          &server->config->param,
                                          conn->param,
                                          silc_connauth_get_ske(connauth))) {
@@ -2130,6 +2194,7 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success,
                                        SILC_STATUS_ERR_PERM_DENIED,
                                        "We do not have connection to backup "
                                        "router established, try later");
+         silc_server_free_sock_user_data(server, sock, NULL);
          server->stat.auth_failures++;
 
          /* From here on, wait 20 seconds for the backup router to appear. */
@@ -2154,9 +2219,11 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success,
        server->stat.auth_failures++;
        silc_server_disconnect_remote(server, sock,
                                      SILC_STATUS_ERR_AUTH_FAILED, NULL);
+       silc_server_free_sock_user_data(server, sock, NULL);
        goto out;
       }
       entry->data.status |= SILC_IDLIST_STATUS_LOCAL;
+      entry->data.conn_type = SILC_CONN_CLIENT;
 
       /* Statistics */
       server->stat.my_clients++;
@@ -2184,6 +2251,7 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success,
       }
 
       /* Add public key to repository */
+      SILC_LOG_DEBUG(("Add client public key to repository"));
       if (!silc_server_get_public_key_by_client(server, client, NULL))
        silc_skr_add_public_key_simple(server->repository,
                                       entry->data.public_key,
@@ -2210,7 +2278,7 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success,
         and we do not have connection to primary router, do not allow
         the connection. */
       if (server->server_type == SILC_BACKUP_ROUTER &&
-         entry->data.conn_type == SILC_CONN_SERVER &&
+         entry->conn_type == SILC_CONN_SERVER &&
          !SILC_PRIMARY_ROUTE(server)) {
        SILC_LOG_INFO(("Will not accept server connection because we do "
                       "not have primary router connection established"));
@@ -2218,14 +2286,15 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success,
                                      SILC_STATUS_ERR_PERM_DENIED,
                                      "We do not have connection to primary "
                                      "router established, try later");
+       silc_server_free_sock_user_data(server, sock, NULL);
        server->stat.auth_failures++;
        goto out;
       }
 
-      if (entry->data.conn_type == SILC_CONN_ROUTER) {
+      if (entry->conn_type == SILC_CONN_ROUTER) {
        /* Verify whether this connection is after all allowed to connect */
        if (!silc_server_connection_allowed(server, sock,
-                                           entry->data.conn_type,
+                                           entry->conn_type,
                                            &server->config->param,
                                            rconn ? rconn->param : NULL,
                                            silc_connauth_get_ske(connauth))) {
@@ -2257,10 +2326,10 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success,
        }
       }
 
-      if (entry->data.conn_type == SILC_CONN_SERVER) {
+      if (entry->conn_type == SILC_CONN_SERVER) {
        /* Verify whether this connection is after all allowed to connect */
        if (!silc_server_connection_allowed(server, sock,
-                                           entry->data.conn_type,
+                                           entry->conn_type,
                                            &server->config->param,
                                            srvconn ? srvconn->param : NULL,
                                            silc_connauth_get_ske(connauth))) {
@@ -2305,6 +2374,7 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success,
                                        SILC_STATUS_ERR_PERM_DENIED,
                                        "We do not have connection to backup "
                                        "router established, try later");
+         silc_server_free_sock_user_data(server, sock, NULL);
          server->stat.auth_failures++;
 
          /* From here on, wait 20 seconds for the backup router to appear. */
@@ -2316,11 +2386,11 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success,
       }
 
       SILC_LOG_DEBUG(("Remote host is %s",
-                     entry->data.conn_type == SILC_CONN_SERVER ?
+                     entry->conn_type == SILC_CONN_SERVER ?
                      "server" : (backup_router ?
                                  "backup router" : "router")));
       SILC_LOG_INFO(("Connection %s (%s) is %s", entry->hostname,
-                    entry->ip, entry->data.conn_type == SILC_CONN_SERVER ?
+                    entry->ip, entry->conn_type == SILC_CONN_SERVER ?
                     "server" : (backup_router ?
                                 "backup router" : "router")));
 
@@ -2329,15 +2399,15 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success,
         server. We mark ourselves as router for this server if we really
         are router. */
       new_server =
-       silc_idlist_add_server((entry->data.conn_type == SILC_CONN_SERVER ?
+       silc_idlist_add_server((entry->conn_type == SILC_CONN_SERVER ?
                                server->local_list : (backup_router ?
                                                      server->local_list :
                                                      server->global_list)),
                               NULL,
-                              (entry->data.conn_type == SILC_CONN_SERVER ?
+                              (entry->conn_type == SILC_CONN_SERVER ?
                                SILC_SERVER : SILC_ROUTER),
                               NULL,
-                              (entry->data.conn_type == SILC_CONN_SERVER ?
+                              (entry->conn_type == SILC_CONN_SERVER ?
                                server->id_entry : (backup_router ?
                                                    server->id_entry : NULL)),
                               sock);
@@ -2345,10 +2415,12 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success,
        SILC_LOG_ERROR(("Could not add new server to cache"));
        silc_server_disconnect_remote(server, sock,
                                      SILC_STATUS_ERR_AUTH_FAILED, NULL);
+       silc_server_free_sock_user_data(server, sock, NULL);
        server->stat.auth_failures++;
        goto out;
       }
       entry->data.status |= SILC_IDLIST_STATUS_LOCAL;
+      entry->data.conn_type = entry->conn_type;
 
       id_entry = (void *)new_server;
 
@@ -2467,6 +2539,7 @@ silc_server_accept_completed(SilcSKE ske, SilcSKEStatus status,
     silc_ske_free(ske);
     silc_server_disconnect_remote(server, sock,
                                  SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
+    silc_server_free_sock_user_data(server, sock, NULL);
     return;
   }
 
@@ -2479,6 +2552,7 @@ silc_server_accept_completed(SilcSKE ske, SilcSKEStatus status,
     silc_ske_free(ske);
     silc_server_disconnect_remote(server, sock,
                                  SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
+    silc_server_free_sock_user_data(server, sock, NULL);
     return;
   }
   silc_packet_set_keys(sock, send_key, receive_key, hmac_send,
@@ -2489,6 +2563,8 @@ silc_server_accept_completed(SilcSKE ske, SilcSKEStatus status,
   pk = silc_pkcs_public_key_encode(idata->public_key, &pk_len);
   silc_hash_make(server->sha1hash, pk, pk_len, idata->fingerprint);
 
+  silc_hash_alloc(silc_hash_get_name(prop->hash), &idata->hash);
+
   SILC_LOG_DEBUG(("Starting connection authentication"));
   server->stat.auth_attempts++;
 
@@ -2499,6 +2575,7 @@ silc_server_accept_completed(SilcSKE ske, SilcSKEStatus status,
     silc_ske_free(ske);
     silc_server_disconnect_remote(server, sock,
                                  SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
+    silc_server_free_sock_user_data(server, sock, NULL);
     return;
   }
 
@@ -2577,6 +2654,7 @@ static void silc_server_accept_new_connection(SilcNetStatus status,
     silc_server_disconnect_remote(server, packet_stream,
                                  SILC_STATUS_ERR_BANNED_FROM_SERVER,
                                  deny->reason);
+    silc_server_free_sock_user_data(server, packet_stream, NULL);
     return;
   }
 
@@ -2595,6 +2673,7 @@ static void silc_server_accept_new_connection(SilcNetStatus status,
     server->stat.conn_failures++;
     silc_server_disconnect_remote(server, packet_stream,
                                  SILC_STATUS_ERR_BANNED_FROM_SERVER, NULL);
+    silc_server_free_sock_user_data(server, packet_stream, NULL);
     return;
   }
 
@@ -2604,6 +2683,7 @@ static void silc_server_accept_new_connection(SilcNetStatus status,
     server->stat.conn_failures++;
     silc_server_disconnect_remote(server, packet_stream,
                                  SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
+    silc_server_free_sock_user_data(server, packet_stream, NULL);
     return;
   }
   entry->hostname = hostname;
@@ -2639,6 +2719,7 @@ static void silc_server_accept_new_connection(SilcNetStatus status,
     server->stat.conn_failures++;
     silc_server_disconnect_remote(server, packet_stream,
                                  SILC_STATUS_ERR_RESOURCE_LIMIT, NULL);
+    silc_server_free_sock_user_data(server, packet_stream, NULL);
     return;
   }
   silc_ske_set_callbacks(ske, silc_server_verify_key,
@@ -2788,7 +2869,7 @@ static void silc_server_rekey(SilcServer server, SilcPacketStream sock,
 
 SILC_TASK_CALLBACK(silc_server_close_connection_final)
 {
-  silc_packet_stream_destroy(context);
+  silc_packet_stream_unref(context);
 }
 
 /* Closes connection to socket connection */
@@ -2801,6 +2882,9 @@ void silc_server_close_connection(SilcServer server,
   const char *hostname;
   SilcUInt16 port;
 
+  if (!silc_packet_stream_is_valid(sock))
+    return;
+
   memset(tmp, 0, sizeof(tmp));
   //  silc_socket_get_error(sock, tmp, sizeof(tmp));
   silc_socket_stream_get_info(silc_packet_stream_get_stream(sock),
@@ -2816,6 +2900,11 @@ void silc_server_close_connection(SilcServer server,
     idata->sconn = NULL;
   }
 
+  /* Take a reference and then destroy the stream.  The last reference
+     is released later in a timeout callback. */
+  silc_packet_stream_ref(sock);
+  silc_packet_stream_destroy(sock);
+
   /* Close connection with timeout */
   server->stat.conn_num--;
   silc_schedule_task_del_by_all(server->schedule, 0,
@@ -2907,8 +2996,10 @@ void silc_server_free_client_data(SilcServer server,
   SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
   silc_schedule_task_del_by_context(server->schedule, client);
 
-  if (client->data.sconn)
+  if (client->data.sconn) {
     silc_server_connection_free(client->data.sconn);
+    client->data.sconn = NULL;
+  }
 
   /* We will not delete the client entry right away. We will take it
      into history (for WHOWAS command) for 5 minutes, unless we're
@@ -2945,7 +3036,7 @@ void silc_server_free_sock_user_data(SilcServer server,
   if (!idata)
     return;
 
-  silc_schedule_task_del_by_context(server->schedule, sock);
+  //  silc_schedule_task_del_by_context(server->schedule, sock);
 
   /* Cancel active protocols */
   if (idata) {
@@ -4067,6 +4158,7 @@ void silc_server_announce_get_inviteban(SilcServer server,
 {
   SilcBuffer list, idp, idp2, tmp2;
   SilcUInt32 type;
+  void *ptype;
   SilcHashTableList htl;
   const unsigned char a[1] = { 0x03 };
 
@@ -4078,9 +4170,10 @@ void silc_server_announce_get_inviteban(SilcServer server,
     type = silc_hash_table_count(channel->invite_list);
     SILC_PUT16_MSB(type, list->data);
     silc_hash_table_list(channel->invite_list, &htl);
-    while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
-      list = silc_argument_payload_encode_one(list, tmp2->data, silc_buffer_len(tmp2),
-                                              type);
+    while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2))
+      list = silc_argument_payload_encode_one(list, tmp2->data,
+                                             silc_buffer_len(tmp2),
+                                             SILC_PTR_TO_32(ptype));
     silc_hash_table_list_reset(&htl);
 
     idp2 = silc_id_payload_encode(server->id, SILC_ID_SERVER);
@@ -4102,9 +4195,10 @@ void silc_server_announce_get_inviteban(SilcServer server,
     type = silc_hash_table_count(channel->ban_list);
     SILC_PUT16_MSB(type, list->data);
     silc_hash_table_list(channel->ban_list, &htl);
-    while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
-      list = silc_argument_payload_encode_one(list, tmp2->data, silc_buffer_len(tmp2),
-                                              type);
+    while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2))
+      list = silc_argument_payload_encode_one(list, tmp2->data,
+                                             silc_buffer_len(tmp2),
+                                             SILC_PTR_TO_32(ptype));
     silc_hash_table_list_reset(&htl);
 
     *ban =