Applied silc-rehash-plus-misc-stuff.patch.
authorGiovanni Giacobbi <johnny@silcnet.org>
Thu, 28 Mar 2002 09:07:33 +0000 (09:07 +0000)
committerGiovanni Giacobbi <johnny@silcnet.org>
Thu, 28 Mar 2002 09:07:33 +0000 (09:07 +0000)
Please see the CHANGES file (Thu Mar 28 09:58:16 CET 2002)
for details.

12 files changed:
CHANGES
apps/silcd/packet_receive.c
apps/silcd/protocol.c
apps/silcd/protocol.h
apps/silcd/server.c
apps/silcd/server.h
apps/silcd/server_internal.h
apps/silcd/serverconfig.c
apps/silcd/serverconfig.h
apps/silcd/serverincludes.h
apps/silcd/silcd.c
lib/silcutil/silclog.c

diff --git a/CHANGES b/CHANGES
index 4b32d3bcd675666900b32a8229ba8357405c372d..4101f61865a68e2044c90aad2d4064edf2fb22a0 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,33 @@
+Thu Mar 28 09:58:16 CET 2002  Johnny Mnemonic <johnny@themnemonic.org>
+
+       * Added functions silc_server_config_[ref/unref], these are used
+         to prevent that the config object is destroyed.
+
+         No longer directly affect global variables silc_log_quick and
+         silc_log_delay, they are first cached inside the config object
+         and then applied with silc_server_config_setlogfiles().
+
+         silc_server_config_set_defaults() is now internal to
+         serverconfig.c, there are no reasons to show this internal stuff
+         to the server.
+
+         Affected files are silcd/serverconfig.[ch].
+
+       * Added macro SILC_SERVER_LOG_STDERR(), this should replace most
+         fprintf's to stderr, since some code may be executed again after
+         the server went into the background.  Affected files are
+         silcd/server.[ch].
+
+       * Added rehash support. Added function silc_server_rehash() that
+         will perform all the basic tasks of the rehashing procedure.
+
+       * Added command line option `-x, --hexdump'. This will enable the
+         SILC_LOG_HEXDUMP calls that are no longer enabled with `--debug'.
+         The option `--hexdump' implies `--debug'.
+
+       * Fixed a bad bug in the logging APIs (silcutil library) where
+         the application would crash after calling silc_log_reset_all().
+
 Wed Mar 27 19:43:16 EET 2002  Pekka Riikonen <priikone@silcnet.org>
 
        * Fixed the KICKED notify handling in client library to
index a3f0848a06252e265ac4bf486adbb317d49330a3..972e60be2e268adcd5812d043e3030ad7ff944ed 100644 (file)
@@ -1877,8 +1877,7 @@ SilcClientEntry silc_server_new_client(SilcServer server,
                           username));
   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
                          ("Your host is %s, running version %s",
-                          server->config->server_info->server_name,
-                          server_version));
+                          server->server_name, server_version));
   if (server->server_type == SILC_ROUTER) {
     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
                            ("There are %d clients on %d servers in SILC "
index 4f9678d1028bc87b607af1c70e373fb91a860b9a..f37c51e845d6093085805ab6848f161a8a7f434f 100644 (file)
@@ -175,8 +175,8 @@ silc_server_protocol_ke_verify_key(SilcSKE ske,
   if (silc_verify_public_key_internal(server, ctx->sock, 
                                      (ctx->responder == FALSE ?
                                       SILC_SOCKET_TYPE_ROUTER:
-                                      ctx->sconfig ? SILC_SOCKET_TYPE_SERVER :
-                                      ctx->rconfig ? SILC_SOCKET_TYPE_ROUTER :
+                                      ctx->sconfig.ref_ptr ? SILC_SOCKET_TYPE_SERVER :
+                                      ctx->rconfig.ref_ptr ? SILC_SOCKET_TYPE_ROUTER :
                                       SILC_SOCKET_TYPE_CLIENT),
                                      pk_data, pk_len, pk_type))
     completion(ske, SILC_SKE_STATUS_OK, completion_context);
@@ -952,8 +952,8 @@ SILC_TASK_CALLBACK(silc_server_protocol_connection_auth)
 
        /* Remote end is client */
        if (conn_type == SILC_SOCKET_TYPE_CLIENT) {
-         SilcServerConfigClient *client = ctx->cconfig;
-         
+         SilcServerConfigClient *client = ctx->cconfig.ref_ptr;
+
          if (client) {
            ret = silc_server_get_authentication(ctx, client->passphrase,
                                                 client->publickeys,
@@ -979,8 +979,8 @@ SILC_TASK_CALLBACK(silc_server_protocol_connection_auth)
        
        /* Remote end is server */
        if (conn_type == SILC_SOCKET_TYPE_SERVER) {
-         SilcServerConfigServer *serv = ctx->sconfig;
-         
+         SilcServerConfigServer *serv = ctx->sconfig.ref_ptr;
+
          if (serv) {
            ret = silc_server_get_authentication(ctx, serv->passphrase,
                                                 serv->publickeys,
@@ -1006,7 +1006,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_connection_auth)
        
        /* Remote end is router */
        if (conn_type == SILC_SOCKET_TYPE_ROUTER) {
-         SilcServerConfigRouter *serv = ctx->rconfig;
+         SilcServerConfigRouter *serv = ctx->rconfig.ref_ptr;
 
          if (serv) {
            ret = silc_server_get_authentication(ctx, serv->passphrase,
index a6ce666a1d28c3a7e94c3a77da40c531c328e2dc..e99f671a715b282afcc82838352494fd075b8a43 100644 (file)
@@ -45,9 +45,9 @@ typedef struct {
   SilcIdType dest_id_type;
 
   /* Pointer to the configurations. */
-  void *cconfig;
-  void *sconfig;
-  void *rconfig;
+  SilcServerConfigRef cconfig;
+  SilcServerConfigRef sconfig;
+  SilcServerConfigRef rconfig;
 
   SilcTask timeout_task;
   SilcPacketContext *packet;
@@ -80,9 +80,9 @@ typedef struct {
   SilcIdType dest_id_type;
 
   /* Pointer to the configurations. */
-  void *cconfig;
-  void *sconfig;
-  void *rconfig;
+  SilcServerConfigRef cconfig;
+  SilcServerConfigRef sconfig;
+  SilcServerConfigRef rconfig;
 
   SilcTask timeout_task;
   SilcPacketContext *packet;
index ffc7f0fc5c2cc67e12d8afdfcc7cc8d3b5bb0b9f..d7f552866ae93706ba206c5cfa839bb5f9a6ae1f 100644 (file)
@@ -108,6 +108,24 @@ void silc_server_free(SilcServer server)
   }
 }
 
+/* Opens a listening port.
+   XXX This function will become more general and will support multiple
+   listening ports */
+
+static bool silc_server_listen(SilcServer server, int *sock)
+{
+
+  *sock = silc_net_create_server(server->config->server_info->port,
+                               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,
+                   server->config->server_info->port));
+    return FALSE;
+  }
+  return TRUE;
+}
+
 /* Initializes the entire SILC server. This is called always before running
    the server. This is called only once at the initialization of the program.
    This binds the server to its listenning port. After this function returns
@@ -115,7 +133,7 @@ void silc_server_free(SilcServer server)
    when everything is ok to run the server. Configuration file must be
    read and parsed before calling this. */
 
-int silc_server_init(SilcServer server)
+bool silc_server_init(SilcServer server)
 {
   int sock;
   SilcServerID *id;
@@ -133,11 +151,12 @@ int silc_server_init(SilcServer server)
     SILC_LOG_ERROR(("Server public key and/or private key does not exist"));
     return FALSE;
   }
+
+  /* Steal public and private key from the config object */
   server->public_key = server->config->server_info->public_key;
   server->private_key = server->config->server_info->private_key;
-
-  /* Set default to configuration parameters */
-  silc_server_config_set_defaults(server);
+  server->config->server_info->public_key = NULL;
+  server->config->server_info->private_key = NULL;
 
   /* Register all configured ciphers, PKCS and hash functions. */
   if (!silc_server_config_register_ciphers(server))
@@ -163,15 +182,13 @@ int silc_server_init(SilcServer server)
   silc_pkcs_public_key_set(server->pkcs, server->public_key);
   silc_pkcs_private_key_set(server->pkcs, server->private_key);
 
-  /* Create a listening server */
-  sock = silc_net_create_server(server->config->server_info->port,
-                               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,
-                   server->config->server_info->port));
+  /* Initialize the scheduler */
+  server->schedule = silc_schedule_init(server->config->param.connections_max);
+  if (!server->schedule)
     goto err;
-  }
+
+  /* First, register log files configuration for error output */
+  silc_server_config_setlogfiles(server);
 
   /* Initialize ID caches */
   server->local_list->clients =
@@ -187,6 +204,10 @@ int silc_server_init(SilcServer server)
   server->global_list->servers = silc_idcache_alloc(0, SILC_ID_SERVER, NULL);
   server->global_list->channels = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL);
 
+  /* Create a listening server */
+  if (!silc_server_listen(server, &sock))
+    goto err;
+
   /* 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
@@ -233,6 +254,7 @@ int silc_server_init(SilcServer 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.
@@ -257,11 +279,6 @@ int silc_server_init(SilcServer server)
   /* Register protocols */
   silc_server_protocols_register();
 
-  /* Initialize the scheduler. */
-  server->schedule = silc_schedule_init(server->config->param.connections_max);
-  if (!server->schedule)
-    goto err;
-
   /* Add the first task to the scheduler. This is task that is executed by
      timeout. It expires as soon as the caller calls silc_server_run. This
      task performs authentication protocol and key exchange with our
@@ -282,9 +299,6 @@ int silc_server_init(SilcServer server)
                         SILC_TASK_PRI_NORMAL);
   server->listenning = TRUE;
 
-  /* Send log file configuration */
-  silc_server_config_setlogfiles(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) {
@@ -335,49 +349,82 @@ int silc_server_init(SilcServer server)
   return FALSE;
 }
 
-/* Fork server to background */
+/* This function basically reads the config file again and switches the config
+   object pointed by the server object. After that, we have to fix various
+   things such as the server_name and the listening ports.
+   Keep in mind that we no longer have the root privileges at this point. */
 
-void silc_server_daemonise(SilcServer server)
+bool silc_server_rehash(SilcServer server)
 {
-  int i;
+  SilcServerConfig newconfig;
 
-  SILC_LOG_DEBUG(("Forking SILC server to background"));
+  /* Reset the logging system */
+  silc_log_quick = TRUE;
+  silc_log_flush_all();
 
-  i = fork();
+  /* Start the main rehash phase (read again the config file) */
+  SILC_LOG_INFO(("Rehashing server"));
+  newconfig = silc_server_config_alloc(server->config_file);
 
-  if (i < 0) {
-    SILC_LOG_DEBUG(("fork() failed, cannot proceed"));
-    exit(1);
+  if (!newconfig) {
+    SILC_LOG_ERROR(("Rehash FAILED."));
+    return FALSE;
   }
-  else if (i) {
-    if (geteuid())
-      SILC_LOG_DEBUG(("Server started as user"));
-    else
-      SILC_LOG_DEBUG(("Server started as root. Dropping privileges."));
-    exit(0);
+  silc_server_config_unref(&server->config_ref);
+  server->config = newconfig;
+  silc_server_config_ref(&server->config_ref, newconfig, (void *) newconfig);
+
+  /* Fix the server_name field */
+  if (!strcmp(server->server_name, newconfig->server_info->server_name)) {
+    /* We don't need any update */
+    silc_free(newconfig->server_info->server_name);
+    newconfig->server_info->server_name = NULL;
+  } else {
+    silc_free(server->server_name);
+    server->server_name = newconfig->server_info->server_name;
+    newconfig->server_info->server_name = NULL;
+
+    /* Update the idcache list with a fresh pointer */
+    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,
+                    server->id_entry->id, server->id_entry, 0, NULL);
   }
-  setsid();
+
+  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 */
+
+  return TRUE;
 }
 
-/* Drop root privligies. If this cannot be done, die. */
+/* Drop root privileges. If some system call fails, die. */
 
 void silc_server_drop(SilcServer server)
 {
   /* Are we executing silcd as root or a regular user? */
-  if (!geteuid()) {
+  if (geteuid()) {
+    SILC_LOG_DEBUG(("Server started as user"));
+  }
+  else {
     struct passwd *pw;
     struct group *gr;
     char *user, *group;
 
+    SILC_LOG_DEBUG(("Server started as root. Dropping privileges."));
+
     /* Get the values given for user and group in configuration file */
     user = server->config->server_info->user;
     group = server->config->server_info->group;
 
     if (!user || !group) {
-      fprintf(stderr, "Error:" /* XXX update this error message */
+      fprintf(stderr, "Error:"
        "\tSILC server must not be run as root.  For the security of your\n"
        "\tsystem it is strongly suggested that you run SILC under dedicated\n"
-       "\tuser account.  Modify the [Identity] configuration section to run\n"
+       "\tuser account.  Modify the ServerInfo configuration section to run\n"
        "\tthe server as non-root user.\n");
       exit(1);
     }
@@ -405,7 +452,7 @@ void silc_server_drop(SilcServer server)
       fprintf(stderr, "Error:"
        "\tSILC server must not be run as root.  For the security of your\n"
        "\tsystem it is strongly suggested that you run SILC under dedicated\n"
-       "\tuser account.  Modify the [Identity] configuration section to run\n"
+       "\tuser account.  Modify the ServerInfo configuration section to run\n"
        "\tthe server as non-root user.\n");
       exit(1);
     }
@@ -438,14 +485,35 @@ void silc_server_drop(SilcServer server)
   }
 }
 
+/* Fork server to background */
+
+void silc_server_daemonise(SilcServer server)
+{
+  int i;
+
+  SILC_LOG_DEBUG(("Forking SILC server to background"));
+
+  if ((i = fork()) < 0) {
+    fprintf(stderr, "Error: fork() failed: %s\n", strerror(errno));
+    exit(1);
+  }
+
+  if (i) /* Kill the parent */
+    exit(0);
+
+  server->background = TRUE;
+  setsid();
+
+  /* XXX close stdin, stdout, stderr -- before this, check that all writes
+     to stderr are changed to SILC_SERVER_LOG_ERROR() */
+}
+
 /* The heart of the server. This runs the scheduler thus runs the server.
    When this returns the server has been stopped and the program will
    be terminated. */
 
 void silc_server_run(SilcServer server)
 {
-  SILC_LOG_DEBUG(("Running server"));
-
   SILC_LOG_INFO(("SILC Server started"));
 
   /* Start the scheduler, the heart of the SILC server. When this returns
@@ -483,7 +551,8 @@ void silc_server_start_key_exchange(SilcServer server,
   SilcSocketConnection newsocket;
   SilcProtocol protocol;
   SilcServerKEInternalContext *proto_ctx;
-  SilcServerConfigRouter *conn = sconn->conn;
+  SilcServerConfigRouter *conn =
+    (SilcServerConfigRouter *) sconn->conn.ref_ptr;
   void *context;
 
   /* Cancel any possible retry timeouts */
@@ -558,8 +627,9 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_retry)
 {
   SilcServerConnection sconn = (SilcServerConnection)context;
   SilcServer server = sconn->server;
+  SilcServerConfigRouter *conn = sconn->conn.ref_ptr;
   SilcServerConfigConnParams *param =
-    (sconn->param ? sconn->param : &server->config->param);
+               (conn->param ? conn->param : &server->config->param);
 
   SILC_LOG_INFO(("Retrying connecting to a router"));
 
@@ -576,16 +646,21 @@ 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 &&
-      param->reconnect_keep_trying == FALSE) {
+  if ((sconn->retry_count > param->reconnect_count) &&
+      !param->reconnect_keep_trying) {
     SILC_LOG_ERROR(("Could not connect to router, giving up"));
+    silc_server_config_unref(&sconn->conn);
     silc_free(sconn->remote_host);
+    silc_free(sconn->backup_replace_ip);
     silc_free(sconn);
     return;
   }
 
+  /* we will lookup a fresh pointer later */
+  silc_server_config_unref(&sconn->conn);
+
   /* Wait one before retrying */
-  silc_schedule_task_add(server->schedule, fd, silc_server_connect_router,
+  silc_schedule_task_add(server->schedule, 0, silc_server_connect_router,
                         context, sconn->retry_timeout, 0,
                         SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
 }
@@ -596,6 +671,7 @@ SILC_TASK_CALLBACK(silc_server_connect_router)
 {
   SilcServerConnection sconn = (SilcServerConnection)context;
   SilcServer server = sconn->server;
+  SilcServerConfigRouter *rconn;
   int sock;
 
   SILC_LOG_INFO(("Connecting to the %s %s on port %d",
@@ -603,6 +679,16 @@ SILC_TASK_CALLBACK(silc_server_connect_router)
                 sconn->remote_host, sconn->remote_port));
 
   server->router_connect = time(NULL);
+  rconn = silc_server_config_find_router_conn(server, sconn->remote_host,
+                                             sconn->remote_port);
+  if (!rconn) {
+    SILC_LOG_INFO(("Unconfigured server, giving up"));
+    silc_free(sconn->remote_host);
+    silc_free(sconn->backup_replace_ip);
+    silc_free(sconn);
+    return;
+  }
+  silc_server_config_ref(&sconn->conn, server->config, (void *)rconn);
 
   /* Connect to remote host */
   sock = silc_net_create_connection(server->config->server_info->server_ip,
@@ -612,10 +698,12 @@ SILC_TASK_CALLBACK(silc_server_connect_router)
     SILC_LOG_ERROR(("Could not connect to router %s:%d",
                    sconn->remote_host, sconn->remote_port));
     if (!sconn->no_reconnect)
-      silc_schedule_task_add(server->schedule, fd,
+      silc_schedule_task_add(server->schedule, 0,
                             silc_server_connect_to_router_retry,
                             context, 0, 1, SILC_TASK_TIMEOUT,
                             SILC_TASK_PRI_NORMAL);
+    else
+      silc_server_config_unref(&sconn->conn);
     return;
   }
 
@@ -668,9 +756,6 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router)
       if (!server->router_conn && !sconn->backup)
        server->router_conn = sconn;
 
-      sconn->conn = ptr;
-      sconn->param = ptr->param;
-
       silc_schedule_task_add(server->schedule, fd,
                             silc_server_connect_router,
                             (void *)sconn, 0, 1, SILC_TASK_TIMEOUT,
@@ -717,7 +802,14 @@ 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);
+    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: "
@@ -745,6 +837,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: "
@@ -765,11 +861,11 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_second)
 
   /* Resolve the authentication method used in this connection. Check if
      we find a match from user configured connections */
-  if (!sconn->conn)
+  if (!sconn->conn.ref_ptr)
     conn = silc_server_config_find_router_conn(server, sock->hostname,
                                               sock->port);
   else
-    conn = sconn->conn;
+    conn = sconn->conn.ref_ptr;
 
   if (conn) {
     /* Match found. Use the configured authentication method. Take only
@@ -852,7 +948,8 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final)
   unsigned char *id_string;
   SilcUInt32 id_len;
   SilcIDListData idata;
-  SilcServerConfigConnParams *param;
+  SilcServerConfigRouter *conn = NULL;
+  SilcServerConfigConnParams *param = NULL;
 
   SILC_LOG_DEBUG(("Start"));
 
@@ -932,7 +1029,10 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final)
   idata = (SilcIDListData)sock->user_data;
   idata->status |= SILC_IDLIST_STATUS_REGISTERED;
 
-  param = (sconn->param ? sconn->param : &server->config->param);
+  conn = sconn->conn.ref_ptr;
+  param = &server->config->param;
+  if (conn && conn->param)
+    param = conn->param;
 
   /* Perform keepalive. The `hb_context' will be freed automatically
      when finally calling the silc_socket_free function. */
@@ -982,6 +1082,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final)
  out:
   /* Free the temporary connection data context */
   if (sconn) {
+    silc_server_config_unref(&sconn->conn);
     silc_free(sconn->remote_host);
     silc_free(sconn->backup_replace_ip);
     silc_free(sconn);
@@ -1002,7 +1103,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final)
   silc_free(ctx);
 }
 
-/* Host lookup callbcak that is called after the incoming connection's
+/* Host lookup callback that is called after the incoming connection's
    IP and FQDN lookup is performed. This will actually check the acceptance
    of the incoming connection and will register the key exchange protocol
    for this connection. */
@@ -1053,7 +1154,7 @@ silc_server_accept_new_connection_lookup(SilcSocketConnection sock,
   if (deny) {
     /* The connection is denied */
     SILC_LOG_INFO(("Connection %s (%s) is denied",
-                   sock->hostname, sock->ip));
+                  sock->hostname, sock->ip));
     silc_server_disconnect_remote(server, sock, deny->reason ?
                                  deny->reason :
                                  "Server closed connection: "
@@ -1062,7 +1163,7 @@ silc_server_accept_new_connection_lookup(SilcSocketConnection sock,
     return;
   }
 
-  /* Check whether we have configred this sort of connection at all. We
+  /* Check whether we have configured 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)))
@@ -1094,12 +1195,12 @@ silc_server_accept_new_connection_lookup(SilcSocketConnection sock,
   proto_ctx->sock = sock;
   proto_ctx->rng = server->rng;
   proto_ctx->responder = TRUE;
-  proto_ctx->cconfig = cconfig;
-  proto_ctx->sconfig = sconfig;
-  proto_ctx->rconfig = rconfig;
+  silc_server_config_ref(&proto_ctx->cconfig, server->config, cconfig);
+  silc_server_config_ref(&proto_ctx->sconfig, server->config, sconfig);
+  silc_server_config_ref(&proto_ctx->rconfig, server->config, 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
+     this is, we go through all found configurations 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);
@@ -1151,6 +1252,7 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection)
   if (sock > server->config->param.connections_max) {
     SILC_LOG_ERROR(("Refusing connection, server is full, try again later"));
     server->stat.conn_failures++;
+    silc_net_close_connection(sock);
     return;
   }
 
@@ -1188,8 +1290,8 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_second)
 
   SILC_LOG_DEBUG(("Start"));
 
-  if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
-      protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
+  if ((protocol->state == SILC_PROTOCOL_STATE_ERROR) ||
+      (protocol->state == SILC_PROTOCOL_STATE_FAILURE)) {
     /* Error occured during protocol */
     silc_protocol_free(protocol);
     sock->protocol = NULL;
@@ -1199,6 +1301,9 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_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_schedule_task_del_by_callback(server->schedule,
                                       silc_server_failure_callback);
@@ -1227,6 +1332,9 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_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_schedule_task_del_by_callback(server->schedule,
                                       silc_server_failure_callback);
@@ -1304,6 +1412,9 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
     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_schedule_task_del_by_callback(server->schedule,
                                       silc_server_failure_callback);
@@ -1319,7 +1430,7 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
   case SILC_SOCKET_TYPE_CLIENT:
     {
       SilcClientEntry client;
-      SilcServerConfigClient *conn = ctx->cconfig;
+      SilcServerConfigClient *conn = ctx->cconfig.ref_ptr;
 
       /* Verify whether this connection is after all allowed to connect */
       if (!silc_server_connection_allowed(server, sock, ctx->conn_type,
@@ -1372,8 +1483,8 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
       bool backup_router = FALSE;
       char *backup_replace_ip = NULL;
       SilcUInt16 backup_replace_port = 0;
-      SilcServerConfigServer *sconn = ctx->sconfig;
-      SilcServerConfigRouter *rconn = ctx->rconfig;
+      SilcServerConfigServer *sconn = ctx->sconfig.ref_ptr;
+      SilcServerConfigRouter *rconn = ctx->rconfig.ref_ptr;
 
       if (ctx->conn_type == SILC_SOCKET_TYPE_ROUTER) {
        /* Verify whether this connection is after all allowed to connect */
@@ -1526,6 +1637,9 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
   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);
   sock->protocol = NULL;
 }
@@ -1994,7 +2108,6 @@ void silc_server_packet_parse_type(SilcServer server,
 
     if (sock->protocol && sock->protocol->protocol &&
        sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_KEY_EXCHANGE) {
-
       SilcServerKEInternalContext *proto_ctx =
        (SilcServerKEInternalContext *)sock->protocol->context;
 
@@ -2279,7 +2392,6 @@ void silc_server_create_connection(SilcServer server,
   sconn->remote_host = strdup(remote_host);
   sconn->remote_port = port;
   sconn->no_reconnect = TRUE;
-  sconn->param = &server->config->param;
 
   silc_schedule_task_add(server->schedule, 0,
                         silc_server_connect_router,
index d442bc033055c1df722d715ec245741dca8bff25..5ce8bbe582029cc3cec46e72b940c9d1a8bad121 100644 (file)
@@ -10,7 +10,7 @@
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
-  
+
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 #ifndef SERVER_H
 #define SERVER_H
 
-/* Forward declaration for SILC Server object. The actual object is
-   defined in internal header file for server routines. I want to keep
-   the object private hence this declaration. */
-typedef struct SilcServerStruct *SilcServer;
-
 /* Forward declaration of backup server context */
 typedef struct SilcServerBackupStruct *SilcServerBackup;
 
@@ -48,9 +43,8 @@ typedef struct {
   int backup_replace_port;
   bool no_reconnect;
 
-  /* Connection configuration (maybe NULL), and connection params */
-  void *conn;
-  void *param;
+  /* Connection configuration (maybe NULL) */
+  SilcServerConfigRef conn;
 
   /* Current connection retry info */
   SilcUInt32 retry_count;
@@ -110,41 +104,49 @@ do {                                                              \
   (sock->protocol && sock->protocol->protocol &&                       \
    sock->protocol->protocol->type == SILC_PROTOCOL_SERVER_REKEY)
 
+/* Output an error message wether to stderr or LOG_ERROR if we are in the
+   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);
-int silc_server_init(SilcServer server);
-void silc_server_daemonise(SilcServer server);
+bool silc_server_init(SilcServer server);
+bool silc_server_rehash(SilcServer server);
 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);
 bool silc_server_packet_parse(SilcPacketParserContext *parser_context,
                              void *context);
-void silc_server_packet_parse_type(SilcServer server, 
+void silc_server_packet_parse_type(SilcServer server,
                                   SilcSocketConnection sock,
                                   SilcPacketContext *packet);
 void silc_server_create_connection(SilcServer server,
                                   const char *remote_host, SilcUInt32 port);
 void silc_server_close_connection(SilcServer server,
                                  SilcSocketConnection sock);
-void silc_server_free_client_data(SilcServer server, 
+void silc_server_free_client_data(SilcServer server,
                                  SilcSocketConnection sock,
-                                 SilcClientEntry client, 
+                                 SilcClientEntry client,
                                  int notify,
                                  const char *signoff);
-void silc_server_free_sock_user_data(SilcServer server, 
+void silc_server_free_sock_user_data(SilcServer server,
                                     SilcSocketConnection sock,
                                     const char *signoff_message);
-void silc_server_remove_from_channels(SilcServer server, 
+void silc_server_remove_from_channels(SilcServer server,
                                      SilcSocketConnection sock,
                                      SilcClientEntry client,
                                      int notify,
                                      char *signoff_message,
                                      int keygen);
-int silc_server_remove_from_one_channel(SilcServer server, 
+int silc_server_remove_from_one_channel(SilcServer server,
                                        SilcSocketConnection sock,
                                        SilcChannelEntry channel,
                                        SilcClientEntry client,
@@ -152,20 +154,20 @@ int silc_server_remove_from_one_channel(SilcServer server,
 void silc_server_disconnect_remote(SilcServer server,
                                   SilcSocketConnection sock,
                                   const char *fmt, ...);
-SilcChannelEntry silc_server_create_new_channel(SilcServer server, 
+SilcChannelEntry silc_server_create_new_channel(SilcServer server,
                                                SilcServerID *router_id,
-                                               char *cipher, 
+                                               char *cipher,
                                                char *hmac,
                                                char *channel_name,
                                                int broadcast);
-SilcChannelEntry 
-silc_server_create_new_channel_with_id(SilcServer server, 
-                                      char *cipher, 
+SilcChannelEntry
+silc_server_create_new_channel_with_id(SilcServer server,
+                                      char *cipher,
                                       char *hmac,
                                       char *channel_name,
                                       SilcChannelID *channel_id,
                                       int broadcast);
-bool silc_server_create_channel_key(SilcServer server, 
+bool silc_server_create_channel_key(SilcServer server,
                                    SilcChannelEntry channel,
                                    SilcUInt32 key_len);
 SilcChannelEntry silc_server_save_channel_key(SilcServer server,
index d0062e11ca3b174eb69c520283d22d509e3903bc..d5bff6ddb94b8a000444c8cd5ce8686a8b7904bf 100644 (file)
@@ -56,7 +56,7 @@ typedef struct {
   SilcUInt32 packets_received;   /* Received packets */
 } SilcServerStatistics;
 
-/* 
+/*
    SILC Server Object.
 
 */
@@ -73,6 +73,7 @@ struct SilcServerStruct {
                                        does not have connection to network. */
   bool listenning;                  /* TRUE if server is listenning for
                                        incoming connections. */
+  bool background;
   SilcServerEntry id_entry;         /* Server's own ID entry */
   SilcServerEntry router;           /* Pointer to the primary router */
   unsigned long router_connect;             /* Time when router was connected */
@@ -111,6 +112,8 @@ struct SilcServerStruct {
 
   /* Configuration object */
   SilcServerConfig config;
+  SilcServerConfigRef config_ref;
+  char *config_file;
 
   /* Random pool */
   SilcRng rng;
index 2153870e0dc904ef599b9a510e7a78de12b49440..11f28a0f2f7c9a11ab387ae1b4b2756e5a7f026f 100644 (file)
@@ -70,7 +70,7 @@ static void my_free_public_key(void *key, void *context, void *user_data)
 }
 
 /* Set default values to those parameters that have not been defined */
-static void 
+static void
 my_set_param_defaults(SilcServerConfigConnParams *params,
                      SilcServerConfigConnParams *defaults)
 {
@@ -85,6 +85,8 @@ my_set_param_defaults(SilcServerConfigConnParams *params,
   SET_PARAM_DEFAULT(reconnect_interval, SILC_SERVER_RETRY_INTERVAL_MIN);
   SET_PARAM_DEFAULT(reconnect_interval_max, SILC_SERVER_RETRY_INTERVAL_MAX);
   SET_PARAM_DEFAULT(key_exchange_rekey, SILC_SERVER_REKEY);
+
+#undef SET_PARAM_DEFAULT
 }
 
 /* Find connection parameters by the parameter block name. */
@@ -98,8 +100,8 @@ my_find_param(SilcServerConfig config, const char *name, SilcUInt32 line)
       return param;
   }
 
-  fprintf(stderr, "\nError while parsing config file at line %lu: "
-         "Cannot find Param \"%s\".\n", line, name);
+  SILC_SERVER_LOG_ERROR(("\nError while parsing config file at line %lu: "
+                        "Cannot find Param \"%s\".\n", line, name));
 
   return NULL;
 }
@@ -121,23 +123,23 @@ static bool my_parse_authdata(SilcAuthMethod auth_meth, char *p,
 
     if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_PEM))
       if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_BIN)) {
-       fprintf(stderr, "\nError while parsing config file at line %lu: "
-               "Could not load public key file!\n", line);
+       SILC_SERVER_LOG_ERROR(("\nError while parsing config file at line %lu: "
+                              "Could not load public key file!\n", line));
        return FALSE;
       }
 
     /* The auth_data is a pointer to the hash table of public keys. */
     if (auth_data) {
       if (*auth_data == NULL)
-       *auth_data = silc_hash_table_alloc(1, silc_hash_public_key, NULL, 
-                                          NULL, NULL, 
-                                          my_free_public_key, NULL, 
+       *auth_data = silc_hash_table_alloc(1, silc_hash_public_key, NULL,
+                                          NULL, NULL,
+                                          my_free_public_key, NULL,
                                           TRUE);
       silc_hash_table_add(*auth_data, public_key, public_key);
     }
   } else {
-    fprintf(stderr, "\nError while parsing config file at line %lu: "
-           "Unknown authentication method.\n", line);
+    SILC_SERVER_LOG_ERROR(("\nError while parsing config file at line %lu: "
+                          "Unknown authentication method.\n", line));
     return FALSE;
   }
   return TRUE;
@@ -378,7 +380,7 @@ SILC_CONFIG_CALLBACK(fetch_pkcs)
 {
   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigPkcs);
 
-  SERVER_CONFIG_DEBUG(("Received PKCS type=%d name=\"%s\" (val=%x)", 
+  SERVER_CONFIG_DEBUG(("Received PKCS type=%d name=\"%s\" (val=%x)",
                       type, name, context));
   if (type == SILC_CONFIG_ARG_BLOCK) {
     /* check the temporary struct's fields */
@@ -441,7 +443,7 @@ SILC_CONFIG_CALLBACK(fetch_serverinfo)
   else if (!strcmp(name, "port")) {
     int port = *(int *)val;
     if ((port <= 0) || (port > 65535)) {
-      fprintf(stderr, "Invalid port number!\n");
+      SILC_SERVER_LOG_ERROR(("Error: line %lu: Invalid port number!\n", line));
       return SILC_CONFIG_ESILENT;
     }
     server_info->port = (SilcUInt16) port;
@@ -479,28 +481,28 @@ SILC_CONFIG_CALLBACK(fetch_serverinfo)
     server_info->pid_file = strdup((char *) val);
   }
   else if (!strcmp(name, "publickey")) {
-    char *tmp = (char *) val;
+    char *file_tmp = (char *) val;
 
     /* try to load specified file, if fail stop config parsing */
-    if (!silc_pkcs_load_public_key(tmp, &server_info->public_key,
+    if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
                                   SILC_PKCS_FILE_PEM))
-      if (!silc_pkcs_load_public_key(tmp, &server_info->public_key,
+      if (!silc_pkcs_load_public_key(file_tmp, &server_info->public_key,
                                     SILC_PKCS_FILE_BIN)) {
-       fprintf(stderr, "\nError: Could not load public key file.");
-       fprintf(stderr, "\n  line %lu: file \"%s\"\n", line, tmp);
+       SILC_SERVER_LOG_ERROR(("Error: Could not load public key file.\n"));
+       SILC_SERVER_LOG_ERROR(("   line %lu: file \"%s\"\n", line, file_tmp));
        return SILC_CONFIG_ESILENT;
       }
   }
   else if (!strcmp(name, "privatekey")) {
-    char *tmp = (char *) val;
+    char *file_tmp = (char *) val;
 
     /* try to load specified file, if fail stop config parsing */
-    if (!silc_pkcs_load_private_key(tmp, &server_info->private_key,
+    if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
                                    SILC_PKCS_FILE_BIN))
-      if (!silc_pkcs_load_private_key(tmp, &server_info->private_key,
+      if (!silc_pkcs_load_private_key(file_tmp, &server_info->private_key,
                                      SILC_PKCS_FILE_PEM)) {
-       fprintf(stderr, "\nError: Could not load private key file.");
-       fprintf(stderr, "\n  line %lu: file \"%s\"\n", line, tmp);
+       SILC_SERVER_LOG_ERROR(("Error: Could not load private key file.\n"));
+       SILC_SERVER_LOG_ERROR(("   line %lu: file \"%s\"\n", line, file_tmp));
        return SILC_CONFIG_ESILENT;
       }
   }
@@ -520,16 +522,16 @@ SILC_CONFIG_CALLBACK(fetch_logging)
   int got_errno;
 
   if (!strcmp(name, "quicklogs")) {
-    silc_log_quick = *(bool *)val;
+    config->logging_quick = *(bool *)val;
   }
   else if (!strcmp(name, "flushdelay")) {
     int flushdelay = *(int *)val;
     if (flushdelay < 2) { /* this value was taken from silclog.h (min delay) */
-      fprintf(stderr, "Error: line %lu: invalid flushdelay value, use "
-               "quicklogs if you want real-time logging.\n", line);
+      SILC_SERVER_LOG_ERROR(("Error: line %lu: Invalid flushdelay value, use "
+                       "quicklogs if you want real-time logging.\n", line));
       return SILC_CONFIG_ESILENT;
     }
-    silc_log_flushdelay = (long) flushdelay;
+    config->logging_flushdelay = (long) flushdelay;
   }
 #define FETCH_LOGGING_CHAN(__chan__, __member__)               \
   else if (!strcmp(name, __chan__)) {                          \
@@ -938,7 +940,7 @@ SILC_CONFIG_CALLBACK(fetch_router)
   else if (!strcmp(name, "port")) {
     int port = *(int *)val;
     if ((port <= 0) || (port > 65535)) {
-      fprintf(stderr, "Invalid port number!\n");
+      SILC_SERVER_LOG_ERROR(("Error: line %lu: Invalid port number!\n", line));
       return SILC_CONFIG_ESILENT;
     }
     tmp->port = (SilcUInt16) port;
@@ -983,7 +985,7 @@ SILC_CONFIG_CALLBACK(fetch_router)
   else if (!strcmp(name, "backupport")) {
     int port = *(int *)val;
     if ((port <= 0) || (port > 65535)) {
-      fprintf(stderr, "Invalid port number!\n");
+      SILC_SERVER_LOG_ERROR(("Error: line %lu: Invalid port number!\n", line));
       return SILC_CONFIG_ESILENT;
     }
     tmp->backup_replace_port = (SilcUInt16) port;
@@ -1175,34 +1177,53 @@ static const SilcConfigTable table_main[] = {
   { 0, 0, 0, 0 }
 };
 
+/* Set default values to stuff that was not configured. */
+
+static void silc_server_config_set_defaults(SilcServerConfig config)
+{
+  my_set_param_defaults(&config->param, NULL);
+
+  config->channel_rekey_secs = (config->channel_rekey_secs ?
+                               config->channel_rekey_secs :
+                               SILC_SERVER_CHANNEL_REKEY);
+  config->key_exchange_timeout = (config->key_exchange_timeout ?
+                                 config->key_exchange_timeout :
+                                 SILC_SERVER_SKE_TIMEOUT);
+  config->conn_auth_timeout = (config->conn_auth_timeout ?
+                              config->conn_auth_timeout :
+                              SILC_SERVER_CONNAUTH_TIMEOUT);
+}
+
 /* Allocates a new configuration object, opens configuration file and
  * parses it. The parsed data is returned to the newly allocated
  * configuration object. */
 
 SilcServerConfig silc_server_config_alloc(char *filename)
 {
-  SilcServerConfig config;
+  SilcServerConfig config_new;
   SilcConfigEntity ent;
   SilcConfigFile *file;
   int ret;
   SILC_LOG_DEBUG(("Loading config data from `%s'", filename));
 
   /* alloc a config object */
-  config = (SilcServerConfig) silc_calloc(1, sizeof(*config));
+  config_new = (SilcServerConfig) silc_calloc(1, sizeof(*config_new));
   /* obtain a config file object */
   file = silc_config_open(filename);
   if (!file) {
-    fprintf(stderr, "\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);
+
   /* load the known configuration options, give our empty object as context */
-  silc_config_register_table(ent, table_main, (void *) config);
+  silc_config_register_table(ent, table_main, (void *) config_new);
+
   /* enter the main parsing loop.  When this returns, we have the parsing
    * result and the object filled (or partially, in case of errors). */
   ret = silc_config_main(ent);
-  SILC_LOG_DEBUG(("Parser returned [ret=%d]: %s", ret, 
+  SILC_LOG_DEBUG(("Parser returned [ret=%d]: %s", ret,
                  silc_config_strerror(ret)));
 
   /* Check if the parser returned errors */
@@ -1211,26 +1232,65 @@ SilcServerConfig silc_server_config_alloc(char *filename)
     if (ret != SILC_CONFIG_ESILENT) {
       char *linebuf, *filename = silc_config_get_filename(file);
       SilcUInt32 line = silc_config_get_line(file);
-      fprintf(stderr, "\nError while parsing config file: %s.\n",
-               silc_config_strerror(ret));
+      SILC_SERVER_LOG_ERROR(("Error while parsing config file: %s.\n",
+                            silc_config_strerror(ret)));
       linebuf = silc_config_read_line(file, line);
-      fprintf(stderr, "  file %s line %lu:  %s\n\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);
 
-  /* XXX FIXME: check for missing mandatory fields */
-  if (!config->server_info) {
-    fprintf(stderr, "\nError: Missing mandatory block `server_info'\n");
+  /* 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_config_destroy(config_new);
     return NULL;
   }
-  return config;
+
+  /* XXX are there any other mandatory sections in the config file? */
+
+  /* Set default to configuration parameters */
+  silc_server_config_set_defaults(config_new);
+
+  return config_new;
+}
+
+/* Increments the reference counter of a config object */
+
+void silc_server_config_ref(SilcServerConfigRef *ref, SilcServerConfig config,
+                           void *ref_ptr)
+{
+  if (ref_ptr) {
+    config->refcount++;
+    ref->config = config;
+    ref->ref_ptr = ref_ptr;
+    SILC_LOG_DEBUG(("Referencing config [%p] New Ref=%hu", config,
+                   config->refcount));
+  }
 }
 
-/* ... */
+/* Decrements the reference counter of a config object.  If the counter
+   reaches 0, the config object is destroyed. */
+
+void silc_server_config_unref(SilcServerConfigRef *ref)
+{
+  SilcServerConfig config = ref->config;
+
+  if (config) {
+    config->refcount--;
+    SILC_LOG_DEBUG(("Unreferencing config [%p] New Ref=%hu", config,
+                   config->refcount));
+    if (!config->refcount)
+      silc_server_config_destroy(config);
+    memset(ref, 0, sizeof(*ref));
+  }
+}
+
+/* Destroy a config object with all his children lists */
 
 void silc_server_config_destroy(SilcServerConfig config)
 {
@@ -1317,6 +1377,9 @@ void silc_server_config_destroy(SilcServerConfig config)
     CONFIG_FREE_AUTH(di);
     silc_free(di);
   }
+
+  memset(config, 'F', sizeof(*config));
+  silc_free(config);
 }
 
 /* Registers configured ciphers. These can then be allocated by the
@@ -1378,7 +1441,7 @@ bool silc_server_config_register_ciphers(SilcServer server)
          silc_sim_getsym(sim, 
            silc_sim_symname(alg_name,
              SILC_CIPHER_SIM_SET_KEY_WITH_STRING));
-       SILC_LOG_DEBUG(("set_key_with_string=%p", 
+       SILC_LOG_DEBUG(("set_key_with_string=%p",
          cipher_obj.set_key_with_string));
        cipher_obj.encrypt =
          silc_sim_getsym(sim, silc_sim_symname(alg_name,
@@ -1571,19 +1634,22 @@ void silc_server_config_setlogfiles(SilcServer server)
   SilcServerConfig config = server->config;
   SilcServerConfigLogging *this;
 
-  SILC_LOG_DEBUG(("Setting configured log file names"));
+  SILC_LOG_DEBUG(("Setting configured log file names and options"));
 
-  if ((this = config->logging_info))
-    silc_log_set_file(SILC_LOG_INFO, this->file, this->maxsize, 
-                     server->schedule);
-  if ((this = config->logging_warnings))
-    silc_log_set_file(SILC_LOG_WARNING, this->file, this->maxsize, 
+  silc_log_quick = config->logging_quick;
+  silc_log_flushdelay = config->logging_flushdelay;
+
+  if ((this = config->logging_fatals))
+    silc_log_set_file(SILC_LOG_FATAL, this->file, this->maxsize,
                      server->schedule);
   if ((this = config->logging_errors))
     silc_log_set_file(SILC_LOG_ERROR, this->file, this->maxsize,
                      server->schedule);
-  if ((this = config->logging_fatals))
-    silc_log_set_file(SILC_LOG_FATAL, this->file, this->maxsize, 
+  if ((this = config->logging_warnings))
+    silc_log_set_file(SILC_LOG_WARNING, this->file, this->maxsize,
+                     server->schedule);
+  if ((this = config->logging_info))
+    silc_log_set_file(SILC_LOG_INFO, this->file, this->maxsize,
                      server->schedule);
 }
 
@@ -1756,24 +1822,3 @@ silc_server_config_get_primary_router(SilcServer server)
 
   return NULL;
 }
-
-/* Set default values to stuff that was not configured. */
-
-bool silc_server_config_set_defaults(SilcServer server)
-{
-  SilcServerConfig config = server->config;
-
-  my_set_param_defaults(&config->param, NULL);
-
-  config->channel_rekey_secs = (config->channel_rekey_secs ? 
-                               config->channel_rekey_secs :
-                               SILC_SERVER_CHANNEL_REKEY);
-  config->key_exchange_timeout = (config->key_exchange_timeout ? 
-                                 config->key_exchange_timeout :
-                                 SILC_SERVER_SKE_TIMEOUT);
-  config->conn_auth_timeout = (config->conn_auth_timeout ? 
-                              config->conn_auth_timeout :
-                              SILC_SERVER_CONNAUTH_TIMEOUT);
-
-  return TRUE;
-}
index b27c7b6564bf2ba89c1cffff4e6c535004d1c891..aafdebd3b713a0c9a82c317ad65e1bb5cb4a8357 100644 (file)
@@ -149,6 +149,9 @@ typedef struct SilcServerConfigRouterStruct {
 typedef struct {
   void *tmp;
 
+  /* Reference count (when this reaches zero, config object is destroyed) */
+  SilcUInt16 refcount;
+
   /* The General section */
   char *module_path;
   bool prefer_passphrase_auth;
@@ -157,6 +160,8 @@ typedef struct {
   SilcUInt32 key_exchange_timeout;
   SilcUInt32 conn_auth_timeout;
   SilcServerConfigConnParams param;
+  bool logging_quick;
+  long logging_flushdelay;
 
   /* Other configuration sections */
   SilcServerConfigCipher *cipher;
@@ -176,11 +181,19 @@ typedef struct {
   SilcServerConfigRouter *routers;
 } *SilcServerConfig;
 
+typedef struct {
+  SilcServerConfig config;
+  void *ref_ptr;
+} SilcServerConfigRef;
+
 /* Prototypes */
 
 /* Basic config operations */
 SilcServerConfig silc_server_config_alloc(char *filename);
 void silc_server_config_destroy(SilcServerConfig config);
+void silc_server_config_ref(SilcServerConfigRef *ref, SilcServerConfig config,
+                           void *ref_ptr);
+void silc_server_config_unref(SilcServerConfigRef *ref);
 
 /* Algorithm registering and reset functions */
 bool silc_server_config_register_ciphers(SilcServer server);
@@ -193,7 +206,7 @@ void silc_server_config_setlogfiles(SilcServer server);
 SilcServerConfigClient *
 silc_server_config_find_client(SilcServer server, char *host);
 SilcServerConfigAdmin *
-silc_server_config_find_admin(SilcServer server, char *host, char *user, 
+silc_server_config_find_admin(SilcServer server, char *host, char *user,
                              char *nick);
 SilcServerConfigDeny *
 silc_server_config_find_denied(SilcServer server, char *host);
@@ -204,6 +217,5 @@ silc_server_config_find_router_conn(SilcServer server, char *host, int port);
 bool silc_server_config_is_primary_route(SilcServer server);
 SilcServerConfigRouter *
 silc_server_config_get_primary_router(SilcServer server);
-bool silc_server_config_set_defaults(SilcServer server);
 
 #endif /* !SERVERCONFIG_H */
index 1b2fa8021002b64e271dc5cdf0d2a9c3cc3136c4..32669956ae4ba9c0cd59a1bef6222f7fdbce3622 100644 (file)
 /* Generic includes */
 #include "silcincludes.h"
 
+/* Forward declaration for SILC Server object. The actual object is
+   defined in internal header file for server routines. I want to keep
+   the object private hence this declaration. */
+typedef struct SilcServerStruct *SilcServer;
+
 /* SILC Server includes */
 #include "idlist.h"
-#include "server.h"
 #include "serverconfig.h"
+#include "server.h"
 #include "serverid.h"
 #include "server_util.h"
 #include "packet_send.h"
index dfe354633f9ab58cac05355e8d9648afede8d550..a935b9e3a6e10d00378317ae91958f3a175a088f 100644 (file)
@@ -34,18 +34,18 @@ static SilcServer silcd;
 
 static void silc_usage(void);
 static char *silc_server_create_identifier(void);
-static int
-silc_server_create_key_pair(char *pkcs_name, int bits, char *path,
-                           char *identifier,
-                           SilcPublicKey *ret_pub_key,
-                           SilcPrivateKey *ret_prv_key);
+static int silc_server_create_key_pair(char *pkcs_name, int bits, char *path,
+                                      char *identifier,
+                                      SilcPublicKey *ret_pub_key,
+                                      SilcPrivateKey *ret_prv_key);
 
 /* Long command line options */
 static struct option long_opts[] =
 {
   { "config-file", 1, NULL, 'f' },
   { "passphrase", 1, NULL, 'p' },
-  { "debug", 1, NULL, 'd' },
+  { "debug", 2, NULL, 'd' },
+  { "hexdump", 0, NULL, 'x' },
   { "help", 0, NULL, 'h' },
   { "foreground", 0, NULL, 'F' },
   { "version", 0, NULL,'V' },
@@ -70,34 +70,35 @@ static int opt_bits = 1024;
 
 static void silc_usage(void)
 {
-  printf("\
-Usage: silcd [options]\n\
-\n\
-  Generic Options:\n\
-  -f  --config-file=FILE        Alternate configuration file\n\
-  -d  --debug=string            Enable debugging (Implies --foreground)\n\
-  -h  --help                    Display this message\n\
-  -F  --foreground              Dont fork\n\
-  -V  --version                 Display version\n\
-\n\
-  Key Management Options:\n\
-  -C, --create-key-pair=PATH    Create new public key pair\n\
-      --pkcs=PKCS               Set the PKCS of the public key pair\n\
-      --bits=VALUE              Set length of the public key pair\n\
-      --identifier=IDENTIFIER   Public key identifier\n\
-\n\
-      The public key identifier may be of the following format:\n\
-\n\
-      UN=<username>, HN=<hostname or IP>, RN=<real name>, E=<email>,\n\
-      O=<organization>, C=<country>\n\
-\n\
-      The UN and HN must be provided, the others are optional.  If the\n\
-      --identifier option is not used an identifier will be created for\n\
-      the public key automatically.\n\
-\n\
-      Example identifier: \"UN=foobar, HN=foo.bar.com, RN=Foo T. Bar, \n\
-                           E=foo@bar.com, C=FI\"\n\
-\n");
+  printf(""
+"Usage: silcd [options]\n"
+"\n"
+"  Generic Options:\n"
+"  -f  --config-file=FILE        Alternate configuration file\n"
+"  -d  --debug=string            Enable debugging (Implies --foreground)\n"
+"  -x  --hexdump                 Enable hexdumps (Implies --debug)\n"
+"  -h  --help                    Display this message\n"
+"  -F  --foreground              Dont fork\n"
+"  -V  --version                 Display version\n"
+"\n"
+"  Key Management Options:\n"
+"  -C, --create-key-pair=PATH    Create new public key pair\n"
+"      --pkcs=PKCS               Set the PKCS of the public key pair\n"
+"      --bits=VALUE              Set length of the public key pair\n"
+"      --identifier=IDENTIFIER   Public key identifier\n"
+"\n"
+"      The public key identifier may be of the following format:\n"
+"\n"
+"      UN=<username>, HN=<hostname or IP>, RN=<real name>, E=<email>,\n"
+"      O=<organization>, C=<country>\n"
+"\n"
+"      The UN and HN must be provided, the others are optional.  If the\n"
+"      --identifier option is not used an identifier will be created for\n"
+"      the public key automatically.\n"
+"\n"
+"      Example identifier: \"UN=foobar, HN=foo.bar.com, RN=Foo T. Bar, \n"
+"                           E=foo@bar.com, C=FI\"\n"
+"\n");
   exit(0);
 }
 
@@ -138,27 +139,40 @@ static void signal_handler(int sig)
 SILC_TASK_CALLBACK(got_hup)
 {
   /* First, reset all log files (they might have been deleted) */
+  /* XXX this may be redundant with the silc_server_config_setlogfiles() call.
+   * merge these two with the appropriate checking. */
   silc_log_reset_all();
-  silc_log_flush_all();
+  /* Rehash the configuration file */
+  silc_server_rehash(silcd);
 }
 
 SILC_TASK_CALLBACK(stop_server)
 {
   /* Stop scheduler, the program will stop eventually after noticing
      that the scheduler is down. */
-  silc_schedule_stop(silcd->schedule); 
+  silc_schedule_stop(silcd->schedule);
+}
+
+void silc_server_stderr(char *message)
+{
+  if (silcd->background)
+    silc_log_output(SILC_LOG_ERROR, message);
+  else {
+    fprintf(stderr, "%s", message);
+    silc_free(message);
+  }
 }
 
 int main(int argc, char **argv)
 {
   int ret, opt, option_index;
-  char *config_file = NULL;
   bool foreground = FALSE;
+  char *silcd_config_file = NULL;
   struct sigaction sa;
 
   /* Parse command line arguments */
   if (argc > 1) {
-    while ((opt = getopt_long(argc, argv, "f:d:hFVC:",
+    while ((opt = getopt_long(argc, argv, "f:p:d::xhFVC:",
                              long_opts, &option_index)) != EOF) {
       switch(opt)
        {
@@ -176,18 +190,30 @@ int main(int argc, char **argv)
        case 'd':
 #ifdef SILC_DEBUG
          silc_debug = TRUE;
+         if (optarg)
+           silc_log_set_debug_string(optarg);
+         foreground = TRUE; /* implied */
+         silc_log_quick = TRUE; /* implied */
+#else
+         fprintf(stderr,
+                 "Run-time debugging is not enabled. To enable it recompile\n"
+                 "the server with --enable-debug configuration option.\n");
+#endif
+         break;
+       case 'x':
+#ifdef SILC_DEBUG
          silc_debug_hexdump = TRUE;
-         silc_log_set_debug_string(optarg);
-         foreground = TRUE;
-         silc_log_quick = TRUE;
+         silc_debug = TRUE; /* implied */
+         foreground = TRUE; /* implied */
+         silc_log_quick = TRUE; /* implied */
 #else
-         fprintf(stdout,
+         fprintf(stderr,
                  "Run-time debugging is not enabled. To enable it recompile\n"
                  "the server with --enable-debug configuration option.\n");
 #endif
          break;
        case 'f':
-         config_file = strdup(optarg);
+         silcd_config_file = strdup(optarg);
          break;
        case 'F':
          foreground = TRUE;
@@ -233,8 +259,8 @@ int main(int argc, char **argv)
   }
 
   /* Default configuration file */
-  if (!config_file)
-    config_file = strdup(SILC_SERVER_CONFIG_FILE);
+  if (!silcd_config_file)
+    silcd_config_file = strdup(SILC_SERVER_CONFIG_FILE);
 
   /* Create SILC Server object */
   ret = silc_server_alloc(&silcd);
@@ -242,16 +268,18 @@ int main(int argc, char **argv)
     goto fail;
 
   /* Read configuration files */
-  silcd->config = silc_server_config_alloc(config_file);
+  silcd->config = silc_server_config_alloc(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 */
   silc_server_checkpid(silcd);
 
   /* Initialize the server */
-  ret = silc_server_init(silcd);
-  if (ret == FALSE)
+  if (silc_server_init(silcd) == FALSE)
     goto fail;
 
   /* Ignore SIGPIPE */
@@ -267,25 +295,26 @@ int main(int argc, char **argv)
   silc_schedule_signal_register(silcd->schedule, SIGTERM, stop_server, NULL);
   silc_schedule_signal_register(silcd->schedule, SIGINT, stop_server, NULL);
 
-  /* Before running the server, fork to background. */
-  if (!foreground)
+  if (!foreground) {
+    /* Drop root. */
+    silc_server_drop(silcd);
+
+    /* Before running the server, fork to background. */
     silc_server_daemonise(silcd);
 
-  /* If set, write pid to file */
-  if (silcd->config->server_info->pid_file) {
-    char buf[10], *pidfile = silcd->config->server_info->pid_file;
-    unlink(pidfile);
-    snprintf(buf, sizeof(buf) - 1, "%d\n", getpid());
-    silc_file_writefile(pidfile, buf, strlen(buf));
+    /* If set, write pid to file */
+    if (silcd->config->server_info->pid_file) {
+      char buf[10], *pidfile = silcd->config->server_info->pid_file;
+      unlink(pidfile);
+      snprintf(buf, sizeof(buf) - 1, "%d\n", getpid());
+      silc_file_writefile(pidfile, buf, strlen(buf));
+    }
   }
 
-  /* Drop root. */
-  silc_server_drop(silcd);
-
   /* Run the server. When this returns the server has been stopped
      and we will exit. */
   silc_server_run(silcd);
-  
+
   /* Stop the server and free it. */
   silc_server_stop(silcd);
   silc_server_free(silcd);
@@ -304,7 +333,7 @@ static char *silc_server_create_identifier(void)
 {
   char *username = NULL, *realname = NULL;
   char hostname[256], email[256];
-  
+
   /* Get realname */
   realname = silc_get_real_name();
 
@@ -327,9 +356,9 @@ static char *silc_server_create_identifier(void)
 /* Creates new public key and private key pair. This is used only
    when user wants to create new key pair from command line. */
 
-static int 
+static int
 silc_server_create_key_pair(char *pkcs_name, int bits, char *path,
-                           char *identifier, 
+                           char *identifier,
                            SilcPublicKey *ret_pub_key,
                            SilcPrivateKey *ret_prv_key)
 {
index 3d371749627f5f05e9e379b7e72af99610b9b634..040f51e0ae4e61c0d76686c3fc7d12f83ed9e17a 100644 (file)
@@ -96,7 +96,7 @@ static SilcLog silc_log_find_by_type(SilcLogType type)
 }
 
 /* Given an open log file, checks the size and rotates it if there is a
- * max size set less then the current size */
+ * max size set lower then the current size */
 static void silc_log_checksize(SilcLog log)
 {
   char newname[127];
@@ -104,12 +104,13 @@ static void silc_log_checksize(SilcLog log)
 
   if (!log || !log->fp || !log->maxsize)
     return; /* we are not interested */
+
   if ((size = ftell(log->fp)) < 0) {
     /* OMG, EBADF is here.. we'll try our best.. */
     FILE *oldfp = log->fp;
     fclose(oldfp); /* we can discard the error */
     log->fp = NULL; /* make sure we don't get here recursively */
-    SILC_LOG_ERROR(("Error while checking size of the log file %s, fp=%d",
+    SILC_LOG_ERROR(("Error while checking size of the log file %s, fp=%p",
                    log->filename, oldfp));
     return;
   }
@@ -148,6 +149,7 @@ static bool silc_log_reset(SilcLog log)
                      log->filename, log->typename, strerror(errno)));
     return FALSE;
   }
+
   return TRUE;
 }
 
@@ -221,7 +223,7 @@ void silc_log_output(SilcLogType type, char *string)
   fprintf(fp, "[%s] [%s] %s\n", silc_get_time(), typename, string);
   if (silc_log_quick || silc_log_starting) {
     fflush(fp);
-    if (log)
+    if (log) /* we may have been redirected to stderr */
       silc_log_checksize(log);
   }
 
@@ -269,12 +271,10 @@ bool silc_log_set_file(SilcLogType type, char *filename, SilcUInt32 maxsize,
     }
   }
 
-  /* remove old file */
+  /* clean the logging channel */
   if (log->filename) {
-    if (log->fp) {
-      fflush(fp);
-      fclose(fp);
-    }
+    if (log->fp)
+      fclose(log->fp);
     silc_free(log->filename);
     log->filename = NULL;
     log->fp = NULL;