From 1f2f026d0f1bafcdbdffd5861502eddda0b876c3 Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Thu, 28 Mar 2002 16:09:22 +0000 Subject: [PATCH] updates. --- CHANGES | 16 ++++ apps/silcd/protocol.h | 4 +- apps/silcd/server.c | 174 ++++++++++++++++++++++---------------- apps/silcd/server.h | 5 +- apps/silcd/serverconfig.c | 47 +++++++--- apps/silcd/serverconfig.h | 3 +- apps/silcd/silcd.c | 5 +- lib/silcutil/silcconfig.c | 2 +- lib/silcutil/silcconfig.h | 2 +- lib/silcutil/silclog.c | 2 +- 10 files changed, 164 insertions(+), 96 deletions(-) diff --git a/CHANGES b/CHANGES index 00c6b56d..a8b37f51 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,19 @@ +Thu Mar 28 17:01:43 EET 2002 Pekka Riikonen + + * 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 * Fixed the TOPIC_SET notify to not cras. It changed the topic diff --git a/apps/silcd/protocol.h b/apps/silcd/protocol.h index e99f671a..f6cc9b1d 100644 --- a/apps/silcd/protocol.h +++ b/apps/silcd/protocol.h @@ -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; diff --git a/apps/silcd/server.c b/apps/silcd/server.c index 92704074..1aab542f 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -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; diff --git a/apps/silcd/server.h b/apps/silcd/server.h index 5ce8bbe5..bd35441e 100644 --- a/apps/silcd/server.h +++ b/apps/silcd/server.h @@ -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 diff --git a/apps/silcd/serverconfig.c b/apps/silcd/serverconfig.c index 11f28a0f..eb743d83 100644 --- a/apps/silcd/serverconfig.c +++ b/apps/silcd/serverconfig.c @@ -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, diff --git a/apps/silcd/serverconfig.h b/apps/silcd/serverconfig.h index aafdebd3..d2e0a40e 100644 --- a/apps/silcd/serverconfig.h +++ b/apps/silcd/serverconfig.h @@ -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); diff --git a/apps/silcd/silcd.c b/apps/silcd/silcd.c index a935b9e3..c2318925 100644 --- a/apps/silcd/silcd.c +++ b/apps/silcd/silcd.c @@ -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(); diff --git a/lib/silcutil/silcconfig.c b/lib/silcutil/silcconfig.c index 460cfd12..de73159a 100644 --- a/lib/silcutil/silcconfig.c +++ b/lib/silcutil/silcconfig.c @@ -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; diff --git a/lib/silcutil/silcconfig.h b/lib/silcutil/silcconfig.h index 06073e4f..a6a20756 100644 --- a/lib/silcutil/silcconfig.h +++ b/lib/silcutil/silcconfig.h @@ -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 * diff --git a/lib/silcutil/silclog.c b/lib/silcutil/silclog.c index 040f51e0..3bd46b35 100644 --- a/lib/silcutil/silclog.c +++ b/lib/silcutil/silclog.c @@ -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]); -- 2.24.0