From: Pekka Riikonen Date: Tue, 25 Jun 2002 21:43:18 +0000 (+0000) Subject: Added preliminary support for non-backup-aware servers in cell X-Git-Tag: silc.toolkit.0.9.3~25 X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=commitdiff_plain;h=675d6cba5a80e53c09c5eb6a03bafffebb6edab0 Added preliminary support for non-backup-aware servers in cell for backup router. Fixed version string parsing crash. Fixed NICK_CHANGE notify crash in client library. --- diff --git a/CHANGES b/CHANGES index d0b13bfa..c046e627 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,32 @@ +Tue Jun 25 18:47:39 EEST 2002 Pekka Riikonen + + * Enable all local server connections before updating client + caches when we've become backup router. Otherwise, signoff + packets may not reach the clients. Affected files are + silcd/server.c and silcd/server_util.[ch]. + + * Fixed a bug in version string parsing which could crash + the program with specially formatted version string. + Bug reported and patch provided by Ville Räsänen. Affected + file lib/silcutil/silcutil.c. + + * Handle the disconnection immediately when DISCONNECT + packet is received in server. Affected file silcd/server.c. + + * Primary router now waits a short time (10 seconds) for + backup router connection before accepting any other + connection (except local). Affected file silcd/server.c, + serverconfig.[ch]. + + * Fixed a crash in client libary in NICK_CHANGE notify when + NICK_CHANGE arrived for client entry we are resolving + currently. Affected file lib/silcclient/client_notify.c. + + * Call the sconn->callback completion even if error had + occurred. Start reconnecting always if connection to + primary router fails during backup router protocol. + Affected files silcd/server.c and server_backup.c. + Mon Jun 24 17:47:52 EEST 2002 Pekka Riikonen * Added functions silc_server_send_opers and diff --git a/TODO b/TODO index 48ae543a..c01886b1 100644 --- a/TODO +++ b/TODO @@ -27,6 +27,9 @@ TODO/bugs In SILC Server the core library, client and server. Maybe implementations of RFC 2425 and RFC 2426 to make it complete. + o Add special handling in router and server for "connection timed out" + error. Be optimistic. + o Backup router related issues (Fix this to 0.9.x): o Complete backup router support with standalone router @@ -35,6 +38,11 @@ TODO/bugs In SILC Server cell use it. When primary goes down, also those that are not using it (are not connected locally) are signoffed. + o When primary goes down and removing clients of non-backup + aware server the SERVER_SIGNOFF includes the router's ID + not the server's ID, which it should include. The notify + is sent by backup. + o Testing o Add a timeout to handling incoming JOIN commands. It should be diff --git a/apps/silcd/idlist.c b/apps/silcd/idlist.c index c9599deb..80d1e91e 100644 --- a/apps/silcd/idlist.c +++ b/apps/silcd/idlist.c @@ -290,13 +290,14 @@ silc_idlist_replace_server_id(SilcIDList id_list, SilcServerID *old_id, int silc_idlist_del_server(SilcIDList id_list, SilcServerEntry entry) { - SILC_LOG_DEBUG(("Start")); - if (entry) { /* Remove from cache */ if (!silc_idcache_del_by_context(id_list->servers, entry)) return FALSE; + SILC_LOG_DEBUG(("Deleting server %s", entry->server_name ? + entry->server_name : "")); + /* Free data */ silc_free(entry->server_name); silc_free(entry->id); diff --git a/apps/silcd/packet_send.c b/apps/silcd/packet_send.c index 5a60a9f9..b159c931 100644 --- a/apps/silcd/packet_send.c +++ b/apps/silcd/packet_send.c @@ -97,8 +97,10 @@ void silc_server_packet_send(SilcServer server, return; /* If entry is disabled do not sent anything. */ - if (idata && idata->status & SILC_IDLIST_STATUS_DISABLED) + if (idata && idata->status & SILC_IDLIST_STATUS_DISABLED) { + SILC_LOG_DEBUG(("Connection is disabled")); return; + } /* Get data used in the packet sending, keys and stuff */ switch(sock->type) { @@ -157,8 +159,10 @@ void silc_server_packet_send_dest(SilcServer server, idata = (SilcIDListData)sock->user_data; /* If entry is disabled do not sent anything. */ - if (idata && idata->status & SILC_IDLIST_STATUS_DISABLED) + if (idata && idata->status & SILC_IDLIST_STATUS_DISABLED) { + SILC_LOG_DEBUG(("Connection is disabled")); return; + } SILC_LOG_DEBUG(("Sending %s packet", silc_get_packet_name(type))); diff --git a/apps/silcd/server.c b/apps/silcd/server.c index 15c1263c..ebb3e811 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -673,6 +673,11 @@ void silc_server_stop(SilcServer server) if (!server->sockets[i]) continue; if (!SILC_IS_LISTENER(server->sockets[i])) { + SilcIDListData idata = server->sockets[i]->user_data; + + if (idata) + idata->status &= ~SILC_IDLIST_STATUS_DISABLED; + silc_schedule_task_del_by_context(server->schedule, server->sockets[i]); silc_server_disconnect_remote(server, server->sockets[i], @@ -920,6 +925,10 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router) ptr->initiator ? "Initiator" : "Responder", ptr->host, ptr->port)); + if (server->server_type == SILC_ROUTER && ptr->backup_router && + ptr->initiator == FALSE && !server->backup_router) + server->wait_backup = TRUE; + if (ptr->initiator) { /* Check whether we are connected to this host already */ if (silc_server_num_sockets_by_remote(server, @@ -995,6 +1004,11 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_second) SILC_TASK_PRI_NORMAL); return; } + + /* Call completion to indicate error */ + if (sconn->callback) + (*sconn->callback)(server, NULL, sconn->callback_context); + silc_server_config_unref(&sconn->conn); silc_free(sconn->remote_host); silc_free(sconn->backup_replace_ip); @@ -1035,6 +1049,11 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_second) SILC_TASK_PRI_NORMAL); return; } + + /* Call completion to indicate error */ + if (sconn->callback) + (*sconn->callback)(server, NULL, sconn->callback_context); + silc_server_config_unref(&sconn->conn); silc_free(sconn->remote_host); silc_free(sconn->backup_replace_ip); @@ -1140,7 +1159,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final) SilcServer server = (SilcServer)ctx->server; SilcServerConnection sconn = (SilcServerConnection)ctx->context; SilcSocketConnection sock = ctx->sock; - SilcServerEntry id_entry; + SilcServerEntry id_entry = NULL; SilcBuffer packet; SilcServerHBContext hb_context; unsigned char *id_string; @@ -1235,7 +1254,8 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final) sock->user_data = (void *)id_entry; sock->type = SILC_SOCKET_TYPE_ROUTER; idata = (SilcIDListData)sock->user_data; - idata->status |= SILC_IDLIST_STATUS_REGISTERED; + idata->status |= (SILC_IDLIST_STATUS_REGISTERED | + SILC_IDLIST_STATUS_LOCAL); conn = sconn->conn.ref_ptr; param = &server->config->param; @@ -1287,12 +1307,12 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final) sock->protocol = NULL; + out: /* Call the completion callback to indicate that we've connected to the router */ if (sconn->callback) (*sconn->callback)(server, id_entry, sconn->callback_context); - out: /* Free the temporary connection data context */ if (sconn) { silc_server_config_unref(&sconn->conn); @@ -1618,6 +1638,14 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_second) SILC_TASK_PRI_LOW); } +/* After this is called, server don't wait for backup router anymore */ + +SILC_TASK_CALLBACK(silc_server_backup_router_wait) +{ + SilcServer server = context; + server->wait_backup = FALSE; +} + /* Final part of accepting new connection. The connection has now been authenticated and keys has been exchanged. We also know whether this is client or server connection. */ @@ -1673,6 +1701,36 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final) goto out; } + /* If we are primary router and we have backup router configured + but it has not connected to use yet, do not accept any other + connection. */ + if (server->wait_backup && server->server_type == SILC_ROUTER && + !server->backup_router) { + SilcServerConfigRouter *router; + router = silc_server_config_get_backup_router(server); + if (router && strcmp(server->config->server_info->primary->server_ip, + sock->ip) && + silc_server_find_socket_by_host(server, + SILC_SOCKET_TYPE_SERVER, + router->backup_replace_ip, 0)) { + SILC_LOG_INFO(("Will not accept connections because we do " + "not have backup router connection established")); + silc_server_disconnect_remote(server, sock, + SILC_STATUS_ERR_PERM_DENIED, + "We do not have connection to backup " + "router established, try later"); + silc_free(sock->user_data); + server->stat.auth_failures++; + + /* From here on, wait 10 seconds for the backup router to appear. */ + silc_schedule_task_add(server->schedule, 0, + silc_server_backup_router_wait, + (void *)server, 10, 0, + SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL); + goto out; + } + } + SILC_LOG_DEBUG(("Remote host is client")); SILC_LOG_INFO(("Connection %s (%s) is client", sock->hostname, sock->ip)); @@ -1780,6 +1838,36 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final) } } + /* If we are primary router and we have backup router configured + but it has not connected to use yet, do not accept any other + connection. */ + if (server->wait_backup && server->server_type == SILC_ROUTER && + !server->backup_router && !backup_router) { + SilcServerConfigRouter *router; + router = silc_server_config_get_backup_router(server); + if (router && strcmp(server->config->server_info->primary->server_ip, + sock->ip) && + silc_server_find_socket_by_host(server, + SILC_SOCKET_TYPE_SERVER, + router->backup_replace_ip, 0)) { + SILC_LOG_INFO(("Will not accept connections because we do " + "not have backup router connection established")); + silc_server_disconnect_remote(server, sock, + SILC_STATUS_ERR_PERM_DENIED, + "We do not have connection to backup " + "router established, try later"); + silc_free(sock->user_data); + server->stat.auth_failures++; + + /* From here on, wait 10 seconds for the backup router to appear. */ + silc_schedule_task_add(server->schedule, 0, + silc_server_backup_router_wait, + (void *)server, 10, 0, + SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL); + goto out; + } + } + SILC_LOG_DEBUG(("Remote host is %s", ctx->conn_type == SILC_SOCKET_TYPE_SERVER ? "server" : (backup_router ? @@ -1829,6 +1917,7 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final) ctx->conn_type = SILC_SOCKET_TYPE_SERVER; new_server->server_type = SILC_BACKUP_ROUTER; + server->wait_backup = FALSE; } /* Statistics */ @@ -2076,7 +2165,7 @@ SILC_TASK_CALLBACK(silc_server_packet_parse_real) /* Check that the the current client ID is same as in the client's packet. */ if (sock->type == SILC_SOCKET_TYPE_CLIENT) { SilcClientEntry client = (SilcClientEntry)sock->user_data; - if (client && client->id) { + if (client && client->id && packet->src_id) { void *id = silc_id_str2id(packet->src_id, packet->src_id_len, packet->src_id_type); if (!id || !SILC_ID_CLIENT_COMPARE(client->id, id)) { @@ -2091,7 +2180,7 @@ SILC_TASK_CALLBACK(silc_server_packet_parse_real) if (server->server_type == SILC_ROUTER) { /* Route the packet if it is not destined to us. Other ID types but server are handled separately after processing them. */ - if (!(packet->flags & SILC_PACKET_FLAG_BROADCAST) && + if (packet->dst_id && !(packet->flags & SILC_PACKET_FLAG_BROADCAST) && packet->dst_id_type == SILC_ID_SERVER && sock->type != SILC_SOCKET_TYPE_CLIENT && memcmp(packet->dst_id, server->id_string, server->id_string_len)) { @@ -2230,6 +2319,11 @@ void silc_server_packet_parse_type(SilcServer server, silc_get_status_message(status), status, message ? message : "")); silc_free(message); + + /* Handle the disconnection from our end too */ + if (sock->user_data && SILC_IS_LOCAL(sock->user_data)) + silc_server_free_sock_user_data(server, sock, NULL); + silc_server_close_connection(server, sock); } break; @@ -2660,7 +2754,10 @@ void silc_server_close_connection(SilcServer server, SilcSocketConnection sock) { if (!server->sockets[sock->sock] && SILC_IS_DISCONNECTED(sock)) { - silc_socket_free(sock); + silc_schedule_task_add(server->schedule, 0, + silc_server_close_connection_final, + (void *)sock, 0, 1, SILC_TASK_TIMEOUT, + SILC_TASK_PRI_NORMAL); return; } @@ -2895,7 +2992,7 @@ void silc_server_free_sock_user_data(SilcServer server, server->router_connect = time(0); server->backup_primary = TRUE; } else { - SILC_LOG_INFO(("We are now new router in this cell")); + SILC_LOG_INFO(("We are now new primary router in this cell")); server->id_entry->router = NULL; server->router = NULL; server->standalone = TRUE; @@ -2942,10 +3039,10 @@ void silc_server_free_sock_user_data(SilcServer server, /* Update the client entries of this server to the new backup router. This also removes the clients that *really* was owned by the primary router and went down with the router. */ + silc_server_local_servers_toggle_enabled(server, TRUE); silc_server_update_clients_by_server(server, user_data, backup_router, TRUE, TRUE); - silc_server_update_servers_by_server(server, user_data, backup_router, - TRUE); + silc_server_update_servers_by_server(server, user_data, backup_router); if (server->server_type == SILC_SERVER) silc_server_update_channels_by_server(server, user_data, backup_router); @@ -4082,13 +4179,12 @@ void silc_server_announce_get_channels(SilcServer server, (*channel_topics)[i] = NULL; silc_server_announce_get_channel_topic(server, channel, &(*channel_topics)[i]); + (*channel_users_modes_c)++; i++; if (!silc_idcache_list_next(list, &id_cache)) break; } - - *channel_users_modes_c += i; } silc_idcache_list_free(list); diff --git a/apps/silcd/server.h b/apps/silcd/server.h index 5ba6a0ba..19828bda 100644 --- a/apps/silcd/server.h +++ b/apps/silcd/server.h @@ -26,7 +26,7 @@ typedef struct SilcServerBackupStruct *SilcServerBackup; /* Callback function that is called after the key exchange and connection authentication protocols has been completed with a remote router. The - `server_entry' is the remote router entry. */ + `server_entry' is the remote router entry or NULL on error. */ typedef void (*SilcServerConnectRouterCallback)(SilcServer server, SilcServerEntry server_entry, void *context); diff --git a/apps/silcd/server_backup.c b/apps/silcd/server_backup.c index 1383e6ce..19b46784 100644 --- a/apps/silcd/server_backup.c +++ b/apps/silcd/server_backup.c @@ -22,6 +22,9 @@ #include "server_internal.h" SILC_TASK_CALLBACK(silc_server_protocol_backup_done); +static void silc_server_backup_connect_primary(SilcServer server, + SilcServerEntry server_entry, + void *context); /* Backup router */ typedef struct { @@ -534,7 +537,7 @@ SILC_TASK_CALLBACK(silc_server_backup_connect_to_router) /* Connect to remote host */ server_ip = server->config->server_info->primary == NULL ? NULL : - server->config->server_info->primary->server_ip; + server->config->server_info->primary->server_ip; sock = silc_net_create_connection(server_ip, sconn->remote_port, sconn->remote_host); if (sock < 0) { @@ -566,6 +569,7 @@ void silc_server_backup_reconnect(SilcServer server, sconn->remote_port = port; sconn->callback = callback; sconn->callback_context = context; + sconn->no_reconnect = TRUE; silc_schedule_task_add(server->schedule, 0, silc_server_backup_connect_to_router, sconn, 1, 0, SILC_TASK_TIMEOUT, @@ -600,8 +604,21 @@ void silc_server_backup_connected(SilcServer server, void *context) { SilcServerBackupProtocolContext proto_ctx; - SilcSocketConnection sock = (SilcSocketConnection)server_entry->connection; + SilcSocketConnection sock; + if (!server_entry) { + /* Try again */ + SilcServerConfigRouter *primary; + primary = silc_server_config_get_primary_router(server); + if (primary) + silc_server_backup_reconnect(server, + primary->host, primary->port, + silc_server_backup_connected, + context); + return; + } + + sock = (SilcSocketConnection)server_entry->connection; proto_ctx = silc_calloc(1, sizeof(*proto_ctx)); proto_ctx->server = server; proto_ctx->sock = sock; @@ -627,12 +644,27 @@ static void silc_server_backup_connect_primary(SilcServer server, void *context) { SilcSocketConnection backup_router = (SilcSocketConnection)context; - SilcSocketConnection sock = (SilcSocketConnection)server_entry->connection; - SilcIDListData idata = (SilcIDListData)server_entry; - SilcServerBackupProtocolContext ctx = - (SilcServerBackupProtocolContext)backup_router->protocol->context; + SilcServerBackupProtocolContext ctx; + SilcSocketConnection sock; + SilcIDListData idata; SilcBuffer buffer; + if (!server_entry) { + /* Try again */ + SilcServerConfigRouter *primary; + primary = silc_server_config_get_primary_router(server); + if (primary) + silc_server_backup_reconnect(server, + primary->host, primary->port, + silc_server_backup_connect_primary, + context); + return; + } + + ctx = (SilcServerBackupProtocolContext)backup_router->protocol->context; + sock = (SilcSocketConnection)server_entry->connection; + idata = (SilcIDListData)server_entry; + SILC_LOG_DEBUG(("Sending CONNECTED packet (session %d)", ctx->session)); /* Send the CONNECTED packet back to the backup router. */ @@ -926,8 +958,9 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup) /* Switch announced informations to our primary router of using the backup router. */ + silc_server_local_servers_toggle_enabled(server, TRUE); silc_server_update_servers_by_server(server, ctx->sock->user_data, - server->router, TRUE); + server->router); silc_server_update_clients_by_server(server, ctx->sock->user_data, server->router, TRUE, FALSE); if (server->server_type == SILC_SERVER) @@ -1054,10 +1087,6 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup) SILC_LOG_INFO(("Switching back to primary router %s", server->router->server_name)); - - /* We cannot talk to backup router connection anymore, it's - enabled again if primary goes down. */ - backup_router->data.status |= SILC_IDLIST_STATUS_DISABLED; } else { /* We are connected to new primary and now continue using it */ router->data.status &= ~SILC_IDLIST_STATUS_DISABLED; @@ -1067,8 +1096,8 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup) /* Update the client entries of the backup router to the new router */ - silc_server_update_servers_by_server(server, backup_router, router, - FALSE); + silc_server_local_servers_toggle_enabled(server, FALSE); + silc_server_update_servers_by_server(server, backup_router, router); silc_server_update_clients_by_server(server, NULL, router, FALSE, FALSE); if (server->server_type == SILC_SERVER) @@ -1142,6 +1171,14 @@ SILC_TASK_CALLBACK(silc_server_protocol_backup_done) server_entry = (SilcServerEntry)id_cache->context; sock = (SilcSocketConnection)server_entry->connection; + /* XXXX */ + if (!sock) { + SILC_LOG_DEBUG(("******** REMOVE THIS TEST, IT ALLOWS A BUG")); + if (!silc_idcache_list_next(list, &id_cache)) + break; + continue; + } + if (sock->protocol == protocol) { sock->protocol = NULL; @@ -1162,6 +1199,14 @@ SILC_TASK_CALLBACK(silc_server_protocol_backup_done) server_entry = (SilcServerEntry)id_cache->context; sock = (SilcSocketConnection)server_entry->connection; + /* XXXX */ + if (!sock) { + SILC_LOG_DEBUG(("******** REMOVE THIS TEST, IT ALLOWS A BUG")); + if (!silc_idcache_list_next(list, &id_cache)) + break; + continue; + } + if (sock->protocol == protocol) { sock->protocol = NULL; diff --git a/apps/silcd/server_internal.h b/apps/silcd/server_internal.h index 1d679b0b..f7e70f46 100644 --- a/apps/silcd/server_internal.h +++ b/apps/silcd/server_internal.h @@ -81,6 +81,8 @@ struct SilcServerStruct { unsigned int backup_router : 1; /* Set if this is backup router */ unsigned int backup_primary : 1; /* Set if we've switched our primary router to a backup router. */ + unsigned int wait_backup : 1; /* Set if we are waiting for backup + router to connect to us. */ SilcServerEntry router; /* Pointer to the primary router */ unsigned long router_connect; /* Time when router was connected */ @@ -163,9 +165,8 @@ typedef struct { #define SILC_BROADCAST(server) (server->server_type == SILC_ROUTER) /* Return TRUE if entry is locally connected or local to us */ -#define SILC_IS_LOCAL(entry) \ - ((entry)->connection ? TRUE : \ - (entry)->data.status & SILC_IDLIST_STATUS_LOCAL ? TRUE : FALSE) +#define SILC_IS_LOCAL(entry) \ + (((SilcIDListData)entry)->status & SILC_IDLIST_STATUS_LOCAL) /* Registers generic task for file descriptor for reading from network and writing to network. As being generic task the actual task is allocated diff --git a/apps/silcd/server_util.c b/apps/silcd/server_util.c index c5b6a696..75091e94 100644 --- a/apps/silcd/server_util.c +++ b/apps/silcd/server_util.c @@ -140,6 +140,9 @@ bool silc_server_remove_clients_by_server(SilcServer server, SilcHashTable channels, clients; int i; + if (!(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) + return FALSE; + SILC_LOG_DEBUG(("Start")); /* Allocate the hash table that holds the channels that require @@ -521,8 +524,12 @@ void silc_server_update_clients_by_server(SilcServer server, client->router = silc_server_update_clients_by_real_server(server, from, client, local, id_cache); - if (!client->router) - client->router = to; + if (!client->router) { + if (server->server_type == SILC_ROUTER) + client->router = from; + else + client->router = to; + } } else { client->router = to; } @@ -532,6 +539,10 @@ void silc_server_update_clients_by_server(SilcServer server, client->router = to; } + if (client->router) + SILC_LOG_DEBUG(("Client changed to %s", + silc_id_render(client->router->id, SILC_ID_CLIENT))); + if (!silc_idcache_list_next(list, &id_cache)) break; } @@ -578,7 +589,7 @@ void silc_server_update_clients_by_server(SilcServer server, silc_server_update_clients_by_real_server(server, from, client, local, id_cache); if (!client->router) - client->router = from; /* on local list put old from */ + client->router = from; } else { client->router = to; } @@ -588,6 +599,10 @@ void silc_server_update_clients_by_server(SilcServer server, client->router = to; } + if (client->router) + SILC_LOG_DEBUG(("Client changed to %s", + silc_id_render(client->router->id, SILC_ID_CLIENT))); + if (!silc_idcache_list_next(list, &id_cache)) break; } @@ -603,46 +618,55 @@ void silc_server_update_clients_by_server(SilcServer server, } /* Updates servers that are from `from' to be originated from `to'. This - will also update the server's connection to `to's connection. If - `local_toggle_enabled' is TRUE then local server's connections are - enabled, if FALSE they are disabled. */ + will also update the server's connection to `to's connection. */ void silc_server_update_servers_by_server(SilcServer server, SilcServerEntry from, - SilcServerEntry to, - bool local_toggle_enabled) + SilcServerEntry to) { SilcIDCacheList list = NULL; SilcIDCacheEntry id_cache = NULL; SilcServerEntry server_entry = NULL; + SILC_LOG_DEBUG(("Updating servers")); + if (silc_idcache_get_all(server->local_list->servers, &list)) { if (silc_idcache_list_first(list, &id_cache)) { while (id_cache) { server_entry = (SilcServerEntry)id_cache->context; - if (SILC_IS_LOCAL(server_entry)) { - if (server_entry != server->id_entry) { - if (local_toggle_enabled) - server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED; - else - server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED; - } - - /* If entry is local to us, do not switch it to any oneelse, - it is ours. */ + /* If entry is local to us, do not switch it to any anyone else, + it is ours. */ + if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry || + server_entry == from) { if (!silc_idcache_list_next(list, &id_cache)) break; else continue; } - if (server_entry->router == from) { - SILC_LOG_DEBUG(("Updating server (local) %s", - server_entry->server_name ? - server_entry->server_name : "")); - server_entry->router = to; - server_entry->connection = to->connection; + /* If we are standalone router, any server that is not directly + connected to cannot exist anymore. If we are not standalone + we update it correctly. */ + if (server->server_type == SILC_ROUTER && server->standalone) { + silc_server_backup_del(server, server_entry); + silc_server_backup_replaced_del(server, server_entry); + silc_idlist_del_data(server_entry); + silc_idlist_del_server(server->local_list, server_entry); + server->stat.servers--; + server->stat.cell_servers--; + } else { + /* XXX if we are not standalone, do a check from local config + whether this server is in our cell, but not connected to + us (in which case we must remove it). */ + + if (server_entry->router == from) { + SILC_LOG_DEBUG(("Updating server (local) %s", + server_entry->server_name ? + server_entry->server_name : "")); + server_entry->router = to; + server_entry->connection = to->connection; + } } if (!silc_idcache_list_next(list, &id_cache)) @@ -657,30 +681,99 @@ void silc_server_update_servers_by_server(SilcServer server, while (id_cache) { server_entry = (SilcServerEntry)id_cache->context; - if (SILC_IS_LOCAL(server_entry)) { - if (server_entry != server->id_entry) { - if (local_toggle_enabled) - server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED; - else - server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED; + /* If entry is local to us, do not switch it to anyone else, + it is ours. */ + if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry || + server_entry == from) { + if (!silc_idcache_list_next(list, &id_cache)) + break; + else + continue; + } + + /* If we are standalone router, any server that is not directly + connected to cannot exist anymore. If we are not standalone + we update it correctly. */ + if (server->server_type == SILC_ROUTER && server->standalone) { + silc_server_backup_del(server, server_entry); + silc_server_backup_replaced_del(server, server_entry); + silc_idlist_del_data(server_entry); + silc_idlist_del_server(server->global_list, server_entry); + server->stat.servers--; + server->stat.cell_servers--; + } else { + /* XXX if we are not standalone, do a check from local config + whether this server is in our cell, but not connected to + us (in which case we must remove it). */ + + if (server_entry->router == from) { + SILC_LOG_DEBUG(("Updating server (global) %s", + server_entry->server_name ? + server_entry->server_name : "")); + server_entry->router = to; + server_entry->connection = to->connection; } + } + + if (!silc_idcache_list_next(list, &id_cache)) + break; + } + } + silc_idcache_list_free(list); + } +} - /* If entry is local to us, do not switch it to anyone else, - it is ours. */ + +/* Toggles the enabled/disabled status of local server connections. Packets + can be sent to the servers when `toggle_enabled' is TRUE and will be + dropped if `toggle_enabled' is FALSE, after this function is called. */ + +void silc_server_local_servers_toggle_enabled(SilcServer server, + bool toggle_enabled) +{ + SilcIDCacheList list = NULL; + SilcIDCacheEntry id_cache = NULL; + SilcServerEntry server_entry = NULL; + + if (silc_idcache_get_all(server->local_list->servers, &list)) { + if (silc_idcache_list_first(list, &id_cache)) { + while (id_cache) { + server_entry = (SilcServerEntry)id_cache->context; + if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry) { if (!silc_idcache_list_next(list, &id_cache)) break; else continue; } - if (server_entry->router == from) { - SILC_LOG_DEBUG(("Updating server (global) %s", - server_entry->server_name ? - server_entry->server_name : "")); - server_entry->router = to; - server_entry->connection = to->connection; + if (toggle_enabled) + server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED; + else + server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED; + + if (!silc_idcache_list_next(list, &id_cache)) + break; + } + } + silc_idcache_list_free(list); + } + + if (silc_idcache_get_all(server->global_list->servers, &list)) { + if (silc_idcache_list_first(list, &id_cache)) { + while (id_cache) { + server_entry = (SilcServerEntry)id_cache->context; + if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry) { + if (!silc_idcache_list_next(list, &id_cache)) + break; + else + continue; } + if (toggle_enabled) + server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED; + else + server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED; + if (!silc_idcache_list_next(list, &id_cache)) break; } @@ -688,7 +781,6 @@ void silc_server_update_servers_by_server(SilcServer server, silc_idcache_list_free(list); } } - /* Removes channels that are from `from. */ void silc_server_remove_channels_by_server(SilcServer server, diff --git a/apps/silcd/server_util.h b/apps/silcd/server_util.h index ec434bc2..6d906485 100644 --- a/apps/silcd/server_util.h +++ b/apps/silcd/server_util.h @@ -46,13 +46,16 @@ void silc_server_update_clients_by_server(SilcServer server, bool remove_from); /* Updates servers that are from `from' to be originated from `to'. This - will also update the server's connection to `to's connection. If - `local_toggle_enabled' is TRUE then local server's connections are - enabled, if FALSE they are disabled. */ -void silc_server_update_servers_by_server(SilcServer server, + will also update the server's connection to `to's connection. */ +void silc_server_update_servers_by_server(SilcServer server, SilcServerEntry from, - SilcServerEntry to, - bool local_toggle_enabled); + SilcServerEntry to); + +/* Toggles the enabled/disabled status of local server connections. Packets + can be sent to the servers when `toggle_enabled' is TRUE and will be + dropped if `toggle_enabled' is FALSE, after this function is called. */ +void silc_server_local_servers_toggle_enabled(SilcServer server, + bool toggle_enabled); /* Removes channels that are from `from. */ void silc_server_remove_channels_by_server(SilcServer server, diff --git a/apps/silcd/serverconfig.c b/apps/silcd/serverconfig.c index 4c576383..0eef766e 100644 --- a/apps/silcd/serverconfig.c +++ b/apps/silcd/serverconfig.c @@ -1853,3 +1853,31 @@ silc_server_config_get_primary_router(SilcServer server) return NULL; } + +/* If we have backup router configured that is going to replace us this + function returns it. */ + +SilcServerConfigRouter * +silc_server_config_get_backup_router(SilcServer server) +{ + SilcServerConfig config = server->config; + SilcServerConfigRouter *serv = NULL; + int i; + + if (server->server_type != SILC_ROUTER) + return NULL; + + serv = config->routers; + for (i = 0; serv; i++) { + if (serv->initiator == FALSE && serv->backup_router == TRUE && + serv->backup_local == TRUE && + !strcmp(server->config->server_info->primary->server_ip, + serv->backup_replace_ip) && + server->config->server_info->primary->port == + serv->backup_replace_port) + return serv; + serv = serv->next; + } + + return NULL; +} diff --git a/apps/silcd/serverconfig.h b/apps/silcd/serverconfig.h index 70674b81..fc6c1095 100644 --- a/apps/silcd/serverconfig.h +++ b/apps/silcd/serverconfig.h @@ -223,5 +223,7 @@ 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); +SilcServerConfigRouter * +silc_server_config_get_backup_router(SilcServer server); #endif /* !SERVERCONFIG_H */ diff --git a/lib/silcclient/client_notify.c b/lib/silcclient/client_notify.c index a137ce47..7258dc92 100644 --- a/lib/silcclient/client_notify.c +++ b/lib/silcclient/client_notify.c @@ -572,6 +572,18 @@ void silc_client_notify_by_server(SilcClient client, goto out; silc_free(client_id); + /* Wait for resolving if necessary */ + if (client_entry->status & SILC_CLIENT_STATUS_RESOLVING) { + SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res)); + res->packet = silc_packet_context_dup(packet); + res->context = client; + res->sock = silc_socket_dup(conn->sock); + silc_client_command_pending(conn, SILC_COMMAND_NONE, + client_entry->resolve_cmd_ident, + silc_client_notify_by_server_pending, res); + goto out; + } + client_entry->valid = FALSE; /* Get new Client ID */ diff --git a/lib/silcutil/silcconfig.c b/lib/silcutil/silcconfig.c index 69375d60..692846f6 100644 --- a/lib/silcutil/silcconfig.c +++ b/lib/silcutil/silcconfig.c @@ -273,16 +273,6 @@ SilcConfigFile *silc_config_open(const char *configfile) void silc_config_close(SilcConfigFile *file) { if (file) { - /* XXX FIXME: this check could probably be removed later */ - SilcUInt32 my_len = (SilcUInt32) (strchr(file->base, EOF) - file->base); - SILC_CONFIG_DEBUG(("file=0x%x name=\"%s\" level=%d line=%lu", - (SilcUInt32) file, file->filename, file->level, - file->line)); - if (my_len != file->len) { - fprintf(stderr, - "FATAL ERROR: saved len and current len does not match!\n"); - abort(); - } silc_free(file->filename); memset(file->base, 'F', file->len); silc_free(file->base); diff --git a/lib/silcutil/silcutil.c b/lib/silcutil/silcutil.c index 57931f7e..8bc4e2c3 100644 --- a/lib/silcutil/silcutil.c +++ b/lib/silcutil/silcutil.c @@ -783,11 +783,12 @@ bool silc_parse_version_string(const char *version, /* Take protocol version */ maj = atoi(cp); - cp = strchr(cp, '.'); - if (cp) { - min = atoi(cp + 1); - cp++; - } + if (!strchr(cp, '.')) + return FALSE; + cp = strchr(cp, '.') + 1; + if (!cp || !(*cp)) + return FALSE; + min = atoi(cp); memset(buf, 0, sizeof(buf)); snprintf(buf, sizeof(buf) - 1, "%d%d", maj, min); @@ -802,14 +803,18 @@ bool silc_parse_version_string(const char *version, maj = 0; min = 0; - cp = strchr(cp, '-'); - if (!cp) + if (!strchr(cp, '-')) + return FALSE; + cp = strchr(cp, '-') + 1; + if (!cp || !(*cp)) return FALSE; - maj = atoi(cp + 1); - cp = strchr(cp, '.'); - if (cp) - min = atoi(cp + 1); + maj = atoi(cp); + if (strchr(cp, '.')) { + cp = strchr(cp, '.') + 1; + if (cp && *cp) + min = atoi(cp); + } memset(buf, 0, sizeof(buf)); snprintf(buf, sizeof(buf) - 1, "%d%d", maj, min); @@ -822,11 +827,10 @@ bool silc_parse_version_string(const char *version, /* Take vendor string */ - cp++; - if (cp) { - cp = strchr(cp, '.'); - if (cp && cp + 1 && vendor_version) - *vendor_version = strdup(cp + 1); + if (strchr(cp, '.')) { + cp = strchr(cp, '.') + 1; + if (cp && *cp && vendor_version) + *vendor_version = strdup(cp); } return TRUE;