Fix use-after-free condition when reconnecting silcd to router silcd.
[silc.git] / apps / silcd / server.c
index 5b655419693626fbce7bd382641c8292b2c52be4..6cef2417d9c3ecd65a55f607390ff406e81c1ec9 100644 (file)
@@ -19,7 +19,6 @@
 
 #include "serverincludes.h"
 #include "server_internal.h"
-#include <assert.h>
 
 /************************* Types and definitions ****************************/
 
@@ -234,7 +233,10 @@ SILC_TASK_CALLBACK(silc_server_packet_error_timeout)
 
   if (server->router_conn && server->router_conn->sock == stream &&
       !server->router && server->standalone) {
+    if (idata->sconn && idata->sconn->callback)
+      (*idata->sconn->callback)(server, NULL, idata->sconn->callback_context);
     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 &&
@@ -282,8 +284,8 @@ static void silc_server_packet_error(SilcPacketEngine engine,
     return;
 
   silc_schedule_task_add_timeout(server->schedule,
-                                silc_server_packet_error_timeout,
-                                stream, 0, 0);
+                                silc_server_packet_error_timeout, stream,
+                                silc_rng_get_byte(server->rng) % 5, 0);
 }
 
 /* Packet stream callbacks */
@@ -768,7 +770,6 @@ SilcBool silc_server_init(SilcServer server)
   SilcNetListener listener;
   SilcUInt16 *port;
   char **ip;
-  char *external_ip;
 
   SILC_LOG_DEBUG(("Initializing server"));
 
@@ -872,11 +873,8 @@ SilcBool silc_server_init(SilcServer server)
   /* Create a Server ID for the server. */
   port = silc_net_listener_get_port(listener, NULL);
   ip = silc_net_listener_get_ip(listener, NULL);
-  external_ip = server->config->server_info->external_ip ?
-               server->config->server_info->external_ip :
-               server->config->server_info->primary->public_ip;
-  silc_id_create_server_id(external_ip ?
-                          external_ip :
+  silc_id_create_server_id(server->config->server_info->primary->public_ip ?
+                          server->config->server_info->primary->public_ip :
                           ip[0], port[0], server->rng, &id);
   if (!id)
     goto err;
@@ -1803,6 +1801,8 @@ void silc_server_start_key_exchange(SilcServerConnection sconn)
   }
   entry->server = server;
   entry->data.sconn = sconn;
+  entry->data.conn_type = SILC_CONN_UNKNOWN;
+  entry->data.status |= SILC_IDLIST_STATUS_LOCAL;
   silc_packet_set_context(sconn->sock, entry);
 
   SILC_LOG_DEBUG(("Created unknown connection %p", entry));
@@ -3134,7 +3134,7 @@ void silc_server_free_client_data(SilcServer server,
 
   /* Update statistics */
   server->stat.my_clients--;
-  assert(server->stat.clients > 0);
+  SILC_VERIFY(server->stat.clients > 0);
   server->stat.clients--;
   if (server->stat.cell_clients)
     server->stat.cell_clients--;