updates. silc.server.0.8.2
authorPekka Riikonen <priikone@silcnet.org>
Thu, 28 Mar 2002 16:09:22 +0000 (16:09 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Thu, 28 Mar 2002 16:09:22 +0000 (16:09 +0000)
CHANGES
apps/silcd/protocol.h
apps/silcd/server.c
apps/silcd/server.h
apps/silcd/serverconfig.c
apps/silcd/serverconfig.h
apps/silcd/silcd.c
lib/silcutil/silcconfig.c
lib/silcutil/silcconfig.h
lib/silcutil/silclog.c

diff --git a/CHANGES b/CHANGES
index 00c6b56db2351e182df15c7bed934529787c8817..a8b37f51ae8021e5fc1b78ba44146f7e247d6ebe 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,19 @@
+Thu Mar 28 17:01:43 EET 2002  Pekka Riikonen <priikone@silcnet.org>
+
+       * Added automatic referencing of config context in the
+         silc_server_config_alloc, and automatic unreferencing in the
+         silc_server_config_destroy.  Affected files are
+         silcd/serverconfig.[ch], silcd/silcd.c.
+
+       * Fixed the silc_log_quick handling in the logging routines.
+         It didn't log quickly when it was TRUE.  Affected file is
+         lib/silcutil/silclog.c.  Also the flush delay was set even
+         if it was 0 in config file.  Affected file is 
+         silcd/serverconfig.c.
+
+       * Added support for changing key pair of the server in rehash.
+         Affected file silcd/server.c.
+
 Thu Mar 28 12:17:21 CET 2002  Pekka Riikonen <priikone@silcnet.org>
 
        * Fixed the TOPIC_SET notify to not cras.  It changed the topic
index e99f671a715b282afcc82838352494fd075b8a43..f6cc9b1dd2c68dd239d72cef7e394ea4e0e0ce0b 100644 (file)
@@ -44,7 +44,7 @@ typedef struct {
   void *dest_id;
   SilcIdType dest_id_type;
 
-  /* Pointer to the configurations. */
+  /* Pointers to the configurations. Defined only when responder is TRUE */
   SilcServerConfigRef cconfig;
   SilcServerConfigRef sconfig;
   SilcServerConfigRef rconfig;
@@ -79,7 +79,7 @@ typedef struct {
   void *dest_id;
   SilcIdType dest_id_type;
 
-  /* Pointer to the configurations. */
+  /* Pointers to the configurations. Defined only when responder is TRUE */
   SilcServerConfigRef cconfig;
   SilcServerConfigRef sconfig;
   SilcServerConfigRef rconfig;
index 927040744a2a2a7afcdcb9930b9301f3b529c6f8..1aab542f6aae01a239566ea5c6db16c7bd4a0174 100644 (file)
@@ -91,6 +91,10 @@ void silc_server_free(SilcServer server)
       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)
@@ -139,6 +143,7 @@ bool silc_server_init(SilcServer server)
   SilcServerID *id;
   SilcServerEntry id_entry;
   SilcIDListPurge purge;
+  SilcSocketConnection newsocket = NULL;
 
   SILC_LOG_DEBUG(("Initializing server"));
   assert(server);
@@ -178,7 +183,8 @@ bool silc_server_init(SilcServer server)
   silc_hash_alloc("sha1", &server->sha1hash);
 
   /* Allocate PKCS context for local public and private keys */
-  silc_pkcs_alloc(server->public_key->name, &server->pkcs);
+  if (!silc_pkcs_alloc(server->public_key->name, &server->pkcs))
+    goto err;
   silc_pkcs_public_key_set(server->pkcs, server->public_key);
   silc_pkcs_private_key_set(server->pkcs, server->private_key);
 
@@ -208,73 +214,71 @@ bool silc_server_init(SilcServer server)
   if (!silc_server_listen(server, &sock))
     goto err;
 
+  /* Set socket to non-blocking mode */
+  silc_net_set_socket_nonblock(sock);
+  server->sock = sock;
+
   /* Allocate the entire socket list that is used in server. Eventually
      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(server->config->param.connections_max,
                                sizeof(*server->sockets));
+  if (!server->sockets)
+    goto err;
 
-  do {
-    SilcSocketConnection newsocket = NULL;
-
-    /* Set socket to non-blocking mode */
-    silc_net_set_socket_nonblock(sock);
-    server->sock = sock;
-
-    /* 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, SILC_SOCKET_TYPE_SERVER, NULL, &newsocket);
-    server->sockets[sock] = newsocket;
-
-    /* Perform name and address lookups to resolve the listenning address
-       and port. */
-    if (!silc_net_check_local_by_sock(sock, &newsocket->hostname,
-                                     &newsocket->ip)) {
-      if ((server->config->require_reverse_lookup && !newsocket->hostname) ||
-         !newsocket->ip) {
-       SILC_LOG_ERROR(("IP/DNS lookup failed for local host %s",
-                       newsocket->hostname ? newsocket->hostname :
-                       newsocket->ip ? newsocket->ip : ""));
-       server->stat.conn_failures++;
-       goto err;
-      }
-      if (!newsocket->hostname)
-       newsocket->hostname = strdup(newsocket->ip);
-    }
-    newsocket->port = silc_net_get_local_port(sock);
-
-    /* Create a Server ID for the server. */
-    silc_id_create_server_id(newsocket->ip, newsocket->port, server->rng, &id);
-    if (!id)
-      goto err;
+  /* 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, SILC_SOCKET_TYPE_SERVER, NULL, &newsocket);
+  server->sockets[sock] = newsocket;
 
-    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;
-
-    /* Add ourselves to the server list. We don't have a router yet
-       beacuse we haven't established a route yet. It will be done later.
-       For now, NULL is sent as router. This allocates new entry to
-       the ID list. */
-    id_entry =
-      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"));
+  /* Perform name and address lookups to resolve the listenning address
+     and port. */
+  if (!silc_net_check_local_by_sock(sock, &newsocket->hostname,
+                                   &newsocket->ip)) {
+    if ((server->config->require_reverse_lookup && !newsocket->hostname) ||
+       !newsocket->ip) {
+      SILC_LOG_ERROR(("IP/DNS lookup failed for local host %s",
+                     newsocket->hostname ? newsocket->hostname :
+                     newsocket->ip ? newsocket->ip : ""));
+      server->stat.conn_failures++;
       goto err;
     }
-    id_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
+    if (!newsocket->hostname)
+      newsocket->hostname = strdup(newsocket->ip);
+  }
+  newsocket->port = silc_net_get_local_port(sock);
+
+  /* Create a Server ID for the server. */
+  silc_id_create_server_id(newsocket->ip, newsocket->port, server->rng, &id);
+  if (!id)
+    goto err;
 
-    /* Put the allocated socket pointer also to the entry allocated above
-       for fast back-referencing to the socket list. */
-    newsocket->user_data = (void *)id_entry;
-    id_entry->connection = (void *)newsocket;
-    server->id_entry = id_entry;
-  } while (0);
+  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;
+
+  /* Add ourselves to the server list. We don't have a router yet
+     beacuse we haven't established a route yet. It will be done later.
+     For now, NULL is sent as router. This allocates new entry to
+     the ID list. */
+  id_entry =
+    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"));
+    goto err;
+  }
+  id_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
+  
+  /* Put the allocated socket pointer also to the entry allocated above
+     for fast back-referencing to the socket list. */
+  newsocket->user_data = (void *)id_entry;
+  id_entry->connection = (void *)newsocket;
+  server->id_entry = id_entry;
 
   /* Register protocols */
   silc_server_protocols_register();
@@ -364,15 +368,24 @@ bool silc_server_rehash(SilcServer server)
 
   /* Start the main rehash phase (read again the config file) */
   SILC_LOG_INFO(("Rehashing server"));
-  newconfig = silc_server_config_alloc(server->config_file);
-
+  newconfig = silc_server_config_alloc(server, server->config_file);
   if (!newconfig) {
     SILC_LOG_ERROR(("Rehash FAILED."));
     return FALSE;
   }
-  silc_server_config_unref(&server->config_ref);
+
+  /* Destroy old config context. This is destroyed if no one is referencing
+     it at the moment. */
+  silc_server_config_destroy(server->config);
   server->config = newconfig;
-  silc_server_config_ref(&server->config_ref, newconfig, (void *) newconfig);
+
+  /* Set public and private keys */
+  if (!server->config->server_info ||
+      !server->config->server_info->public_key ||
+      !server->config->server_info->private_key) {
+    SILC_LOG_ERROR(("Server public key and/or private key does not exist"));
+    return FALSE;
+  }
 
   /* Fix the server_name field */
   if (!strcmp(server->server_name, newconfig->server_info->server_name)) {
@@ -388,15 +401,31 @@ bool silc_server_rehash(SilcServer server)
     silc_free(server->id_entry->server_name);
     server->id_entry->server_name = strdup(server->server_name);
     silc_idcache_del_by_context(server->local_list->servers, server->id_entry);
-    silc_idcache_add(server->local_list->servers, server->id_entry->server_name,
+    silc_idcache_add(server->local_list->servers, 
+                    server->id_entry->server_name,
                     server->id_entry->id, server->id_entry, 0, NULL);
   }
 
   silc_server_config_setlogfiles(server);
 
-  /* XXX There is still to implement the publickey change and modules
-     adding (we can't allow modules removing since we can't know which
-     one are actually in use */
+  /* Change new key pair if necessary */
+  if (server->config->server_info->public_key &&
+      !silc_pkcs_public_key_compare(server->public_key,
+                                   server->config->server_info->public_key)) {
+    silc_pkcs_public_key_free(server->public_key);
+    silc_pkcs_private_key_free(server->private_key);
+    server->public_key = server->config->server_info->public_key;
+    server->private_key = server->config->server_info->private_key;
+    server->config->server_info->public_key = NULL;
+    server->config->server_info->private_key = NULL;
+
+    /* Allocate PKCS context for local public and private keys */
+    silc_pkcs_free(server->pkcs);
+    if (!silc_pkcs_alloc(server->public_key->name, &server->pkcs))
+      return FALSE;
+    silc_pkcs_public_key_set(server->pkcs, server->public_key);
+    silc_pkcs_private_key_set(server->pkcs, server->private_key);
+  }
 
   return TRUE;
 }
@@ -656,7 +685,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_retry)
     return;
   }
 
-  /* we will lookup a fresh pointer later */
+  /* We will lookup a fresh pointer later */
   silc_server_config_unref(&sconn->conn);
 
   /* Wait one before retrying */
@@ -682,7 +711,9 @@ SILC_TASK_CALLBACK(silc_server_connect_router)
   rconn = silc_server_config_find_router_conn(server, sconn->remote_host,
                                              sconn->remote_port);
   if (!rconn) {
-    SILC_LOG_INFO(("Unconfigured server, giving up"));
+    SILC_LOG_INFO(("Unconfigured %s connection %s:%d, cannot connect",
+                  (sconn->backup ? "backup router" : "router"),
+                  sconn->remote_host, sconn->remote_port));
     silc_free(sconn->remote_host);
     silc_free(sconn->backup_replace_ip);
     silc_free(sconn);
@@ -798,9 +829,6 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_second)
     if (ctx->ske)
       silc_ske_free(ctx->ske);
     silc_free(ctx->dest_id);
-    silc_server_config_unref(&ctx->cconfig);
-    silc_server_config_unref(&ctx->sconfig);
-    silc_server_config_unref(&ctx->rconfig);
     silc_free(ctx);
     silc_server_config_unref(&sconn->conn);
     silc_free(sconn->remote_host);
@@ -891,6 +919,10 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_second)
       silc_ske_free(ctx->ske);
     silc_free(ctx->dest_id);
     silc_free(ctx);
+    silc_server_config_unref(&sconn->conn);
+    silc_free(sconn->remote_host);
+    silc_free(sconn->backup_replace_ip);
+    silc_free(sconn);
     silc_schedule_task_del_by_callback(server->schedule,
                                       silc_server_failure_callback);
     silc_server_disconnect_remote(server, sock, "Server closed connection: "
@@ -1246,7 +1278,7 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection)
 
   /* Check for maximum allowed connections */
   if (sock > server->config->param.connections_max) {
-    SILC_LOG_ERROR(("Refusing connection, server is full, try again later"));
+    SILC_LOG_ERROR(("Refusing connection, server is full"));
     server->stat.conn_failures++;
     silc_net_close_connection(sock);
     return;
index 5ce8bbe582029cc3cec46e72b940c9d1a8bad121..bd35441e4eea4ab5a5e755cf98e9310f92a9468d 100644 (file)
@@ -85,6 +85,7 @@ typedef struct {
 #define SILC_SERVER_CONNAUTH_TIMEOUT   60       /* CONN_AUTH timeout */
 #define SILC_SERVER_MAX_CONNECTIONS    1000     /* Max connections */
 #define SILC_SERVER_MAX_CONNECTIONS_SINGLE 1000  /* Max connections per host */
+#define SILC_SERVER_LOG_FLUSH_DELAY    300       /* Default log flush delay */
 
 /* Macros */
 
@@ -108,8 +109,6 @@ do {                                                                \
    background. */
 #define SILC_SERVER_LOG_ERROR(fmt) silc_server_stderr(silc_format fmt)
 
-
-
 /* Prototypes */
 int silc_server_alloc(SilcServer *new_server);
 void silc_server_free(SilcServer server);
@@ -119,7 +118,6 @@ void silc_server_drop(SilcServer server);
 void silc_server_daemonise(SilcServer server);
 void silc_server_run(SilcServer server);
 void silc_server_stop(SilcServer server);
-void silc_server_stderr(char *message);
 void silc_server_start_key_exchange(SilcServer server,
                                    SilcServerConnection sconn,
                                    int sock);
@@ -222,5 +220,6 @@ SilcBuffer silc_server_get_client_channel_list(SilcServer server,
 SilcClientEntry silc_server_get_client_resolve(SilcServer server,
                                               SilcClientID *client_id,
                                               bool *resolved);
+void silc_server_stderr(char *message);
 
 #endif
index 11f28a0f2f7c9a11ab387ae1b4b2756e5a7f026f..eb743d834de81fe472f17e0f9dd1f3bfa01a8200 100644 (file)
@@ -1198,7 +1198,8 @@ static void silc_server_config_set_defaults(SilcServerConfig config)
  * parses it. The parsed data is returned to the newly allocated
  * configuration object. */
 
-SilcServerConfig silc_server_config_alloc(char *filename)
+SilcServerConfig silc_server_config_alloc(SilcServer server,
+                                         const char *filename)
 {
   SilcServerConfig config_new;
   SilcConfigEntity ent;
@@ -1207,13 +1208,18 @@ SilcServerConfig silc_server_config_alloc(char *filename)
   SILC_LOG_DEBUG(("Loading config data from `%s'", filename));
 
   /* alloc a config object */
-  config_new = (SilcServerConfig) silc_calloc(1, sizeof(*config_new));
+  config_new = silc_calloc(1, sizeof(*config_new));
+  if (!config_new)
+    return NULL;
+
   /* obtain a config file object */
   file = silc_config_open(filename);
   if (!file) {
-    SILC_SERVER_LOG_ERROR(("\nError: can't open config file `%s'\n", filename));
+    SILC_SERVER_LOG_ERROR(("\nError: can't open config file `%s'\n", 
+                          filename));
     return NULL;
   }
+
   /* obtain a SilcConfig entity, we can use it to start the parsing */
   ent = silc_config_init(file);
 
@@ -1235,18 +1241,21 @@ SilcServerConfig silc_server_config_alloc(char *filename)
       SILC_SERVER_LOG_ERROR(("Error while parsing config file: %s.\n",
                             silc_config_strerror(ret)));
       linebuf = silc_config_read_line(file, line);
-      SILC_SERVER_LOG_ERROR(("  file %s line %lu:  %s\n", filename, line, linebuf));
+      SILC_SERVER_LOG_ERROR(("  file %s line %lu:  %s\n", filename, 
+                            line, linebuf));
       silc_free(linebuf);
     }
     silc_server_config_destroy(config_new);
     return NULL;
   }
+
   /* close (destroy) the file object */
   silc_config_close(file);
 
   /* If config_new is incomplete, abort the object and return NULL */
   if (!config_new->server_info) {
-    SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block `server_info'\n"));
+    SILC_SERVER_LOG_ERROR(("\nError: Missing mandatory block "
+                          "`server_info'\n"));
     silc_server_config_destroy(config_new);
     return NULL;
   }
@@ -1256,6 +1265,7 @@ SilcServerConfig silc_server_config_alloc(char *filename)
   /* Set default to configuration parameters */
   silc_server_config_set_defaults(config_new);
 
+  silc_server_config_ref(&server->config_ref, config_new, config_new);
   return config_new;
 }
 
@@ -1268,8 +1278,8 @@ void silc_server_config_ref(SilcServerConfigRef *ref, SilcServerConfig config,
     config->refcount++;
     ref->config = config;
     ref->ref_ptr = ref_ptr;
-    SILC_LOG_DEBUG(("Referencing config [%p] New Ref=%hu", config,
-                   config->refcount));
+    SILC_LOG_DEBUG(("Referencing config [%p] refcnt %hu->%hu", config,
+                   config->refcount - 1, config->refcount));
   }
 }
 
@@ -1279,14 +1289,12 @@ void silc_server_config_ref(SilcServerConfigRef *ref, SilcServerConfig config,
 void silc_server_config_unref(SilcServerConfigRef *ref)
 {
   SilcServerConfig config = ref->config;
-
-  if (config) {
+  if (ref->ref_ptr) {
     config->refcount--;
-    SILC_LOG_DEBUG(("Unreferencing config [%p] New Ref=%hu", config,
-                   config->refcount));
+    SILC_LOG_DEBUG(("Unreferencing config [%p] refcnt %hu->%hu", config,
+                   config->refcount + 1, config->refcount));
     if (!config->refcount)
       silc_server_config_destroy(config);
-    memset(ref, 0, sizeof(*ref));
   }
 }
 
@@ -1295,6 +1303,17 @@ void silc_server_config_unref(SilcServerConfigRef *ref)
 void silc_server_config_destroy(SilcServerConfig config)
 {
   void *tmp;
+
+  if (config->refcount > 0) {
+    config->refcount--;
+    SILC_LOG_DEBUG(("Unreferencing config [%p] refcnt %hu->%hu", config,
+                   config->refcount + 1, config->refcount));
+    if (config->refcount > 0)
+      return;
+  }
+
+  SILC_LOG_DEBUG(("Freeing config context"));
+
   silc_free(config->module_path);
 
   /* Destroy Logging channels */
@@ -1637,7 +1656,9 @@ void silc_server_config_setlogfiles(SilcServer server)
   SILC_LOG_DEBUG(("Setting configured log file names and options"));
 
   silc_log_quick = config->logging_quick;
-  silc_log_flushdelay = config->logging_flushdelay;
+  silc_log_flushdelay = (config->logging_flushdelay ? 
+                        config->logging_flushdelay :
+                        SILC_SERVER_LOG_FLUSH_DELAY);
 
   if ((this = config->logging_fatals))
     silc_log_set_file(SILC_LOG_FATAL, this->file, this->maxsize,
index aafdebd3b713a0c9a82c317ad65e1bb5cb4a8357..d2e0a40eccda21662a79e2d5532458d9ea6638f5 100644 (file)
@@ -189,7 +189,8 @@ typedef struct {
 /* Prototypes */
 
 /* Basic config operations */
-SilcServerConfig silc_server_config_alloc(char *filename);
+SilcServerConfig silc_server_config_alloc(SilcServer server, 
+                                         const char *filename);
 void silc_server_config_destroy(SilcServerConfig config);
 void silc_server_config_ref(SilcServerConfigRef *ref, SilcServerConfig config,
                            void *ref_ptr);
index a935b9e3a6e10d00378317ae91958f3a175a088f..c2318925f06e52c9596e32555e6f5360bc14199b 100644 (file)
@@ -268,11 +268,9 @@ int main(int argc, char **argv)
     goto fail;
 
   /* Read configuration files */
-  silcd->config = silc_server_config_alloc(silcd_config_file);
+  silcd->config = silc_server_config_alloc(silcd, silcd_config_file);
   if (silcd->config == NULL)
     goto fail;
-  silc_server_config_ref(&silcd->config_ref, silcd->config,
-                        (void *)silcd->config);
   silcd->config_file = silcd_config_file;
 
   /* Check for another silcd running */
@@ -318,6 +316,7 @@ int main(int argc, char **argv)
   /* Stop the server and free it. */
   silc_server_stop(silcd);
   silc_server_free(silcd);
+  silc_server_config_destroy(silcd->config);
 
   /* Flush the logging system */
   silc_log_flush_all();
index 460cfd1214a247a2e149fd77e205f4c3e786eeb7..de73159a79e41fd4e8b9cea321af9d904b814ed7 100644 (file)
@@ -250,7 +250,7 @@ static void *silc_config_marshall(SilcConfigType type, const char *val)
 /* Tries to open the config file and returns a valid SilcConfigFile object
  * or NULL if failed */
 
-SilcConfigFile *silc_config_open(char *configfile)
+SilcConfigFile *silc_config_open(const char *configfile)
 {
   char *buffer;
   SilcUInt32 filelen;
index 06073e4f2f9352c9bcb9d93aba757e3a049edc11..a6a20756db75b05a95b5b76e176d75a0d23dc7ba 100644 (file)
@@ -268,7 +268,7 @@ static int func(SilcConfigType type, const char *name,              \
  *    silc_config_close().
  *
  ***/
-SilcConfigFile *silc_config_open(char *configfile);
+SilcConfigFile *silc_config_open(const char *configfile);
 
 /****f* silcutil/SilcConfigAPI/silc_config_close
  *
index 040f51e0ae4e61c0d76686c3fc7d12f83ed9e17a..3bd46b3554b051000903afdf8a1e8ed38aa78f2e 100644 (file)
@@ -158,7 +158,7 @@ static bool silc_log_reset(SilcLog log)
 SILC_TASK_CALLBACK(silc_log_fflush_callback)
 {
   unsigned int u;
-  if (!silc_log_quick) {
+  if (silc_log_quick) {
     silc_log_flush_all();
     SILC_FOREACH_LOG(u)
       silc_log_checksize(&silclogs[u]);