From ad84e8073e747c282e234e14e21a78bad24960cb Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Wed, 26 Jun 2002 12:33:36 +0000 Subject: [PATCH] Added silc_server_remove_servers_by_server to remove servers and clients of those servers. --- CHANGES | 10 +++ TODO | 4 ++ apps/silcd/packet_receive.c | 11 +++- apps/silcd/packet_send.c | 27 +++++--- apps/silcd/server.c | 68 +++++++++++-------- apps/silcd/server_backup.c | 2 +- apps/silcd/server_util.c | 126 ++++++++++++++++++++++++++++-------- apps/silcd/server_util.h | 19 ++++-- 8 files changed, 194 insertions(+), 73 deletions(-) diff --git a/CHANGES b/CHANGES index b6eb31ec..6d87f8ed 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,13 @@ +Wed Jun 26 15:14:12 EEST 2002 Pekka Riikonen + + * Stop for a couple seconds after badkup router has become + primary router. Affected file silcd/server.c. + + * Added silc_server_remove_servers_by_server, which is used + to remove servers originated from some other server. Also + clients of those servers can be removed too. Affected file + silcd/server_util.[ch]. + Wed Jun 26 10:38:11 EEST 2002 Pekka Riikonen * Fixed a bug in silc_string_regexify which did not add '^' diff --git a/TODO b/TODO index b3e6b13c..911a25ad 100644 --- a/TODO +++ b/TODO @@ -43,6 +43,10 @@ TODO/bugs In SILC Server not the server's ID, which it should include. The notify is sent by backup. + o When removing clients by server in signoff, EOF etc, find also + the client's real server (based on the Client ID's IP), and + remove the server too. + o Testing o Close unconfigured client connections in rehash. diff --git a/apps/silcd/packet_receive.c b/apps/silcd/packet_receive.c index 4abfcfb8..4e07b0ce 100644 --- a/apps/silcd/packet_receive.c +++ b/apps/silcd/packet_receive.c @@ -1298,9 +1298,14 @@ void silc_server_notify(SilcServer server, if (SILC_IS_LOCAL(server_entry)) break; - /* Free all client entries that this server owns as they will - become invalid now as well. */ - silc_server_remove_clients_by_server(server, server_entry, TRUE); + /* Remove all servers that are originated from this server, and + remove the clients of those servers too. */ + silc_server_remove_servers_by_server(server, server_entry, TRUE); + + /* Remove the clients that this server owns as they will become + invalid now too. */ + silc_server_remove_clients_by_server(server, server_entry, + server_entry, TRUE); silc_server_backup_del(server, server_entry); /* Remove the server entry */ diff --git a/apps/silcd/packet_send.c b/apps/silcd/packet_send.c index b159c931..7d7e0a5e 100644 --- a/apps/silcd/packet_send.c +++ b/apps/silcd/packet_send.c @@ -97,7 +97,8 @@ 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) || + sock->user_data == server->id_entry) { SILC_LOG_DEBUG(("Connection is disabled")); return; } @@ -159,7 +160,8 @@ 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) || + sock->user_data == server->id_entry) { SILC_LOG_DEBUG(("Connection is disabled")); return; } @@ -257,6 +259,20 @@ void silc_server_packet_send_srcdest(SilcServer server, /* Get data used in the packet sending, keys and stuff */ idata = (SilcIDListData)sock->user_data; + /* If entry is disabled do not sent anything. */ + if ((idata && idata->status & SILC_IDLIST_STATUS_DISABLED) || + sock->user_data == server->id_entry) { + SILC_LOG_DEBUG(("Connection is disabled")); + return; + } + + if (idata) { + cipher = idata->send_key; + hmac = idata->hmac_send; + sequence = idata->psn_send++; + block_len = silc_cipher_get_block_len(cipher); + } + if (dst_id) { dst_id_data = silc_id_id2str(dst_id, dst_id_type); dst_id_len = silc_id_get_len(dst_id, dst_id_type); @@ -267,13 +283,6 @@ void silc_server_packet_send_srcdest(SilcServer server, src_id_len = silc_id_get_len(src_id, src_id_type); } - if (idata) { - cipher = idata->send_key; - hmac = idata->hmac_send; - sequence = idata->psn_send++; - block_len = silc_cipher_get_block_len(cipher); - } - /* Set the packet context pointers */ packetdata.type = type; packetdata.flags = flags; diff --git a/apps/silcd/server.c b/apps/silcd/server.c index ebb3e811..75e84719 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -893,20 +893,15 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router) SilcServerConnection sconn; SilcServerConfigRouter *ptr; - SILC_LOG_DEBUG(("Connecting to router(s)")); - - if (server->server_type == SILC_SERVER) { - SILC_LOG_DEBUG(("We are normal server")); - } else if (server->server_type == SILC_ROUTER) { - SILC_LOG_DEBUG(("We are router")); - } else { - SILC_LOG_DEBUG(("We are backup router/normal server")); - } + SILC_LOG_DEBUG(("We are %s", + (server->server_type == SILC_SERVER ? + "normal server" : server->server_type == SILC_ROUTER ? + "router" : "backup router/normal server"))); if (!server->config->routers) { /* There wasn't a configured router, we will continue but we don't have a connection to outside world. We will be standalone server. */ - SILC_LOG_DEBUG(("No router(s), server will be standalone")); + SILC_LOG_DEBUG(("No router(s), we are standalone")); server->standalone = TRUE; return; } @@ -2996,6 +2991,9 @@ void silc_server_free_sock_user_data(SilcServer server, server->id_entry->router = NULL; server->router = NULL; server->standalone = TRUE; + + /* We stop here to take a breath */ + sleep(2); } if (server->server_type == SILC_BACKUP_ROUTER) { @@ -3024,24 +3022,38 @@ void silc_server_free_sock_user_data(SilcServer server, } if (!backup_router) { - /* As router, remove clients and channels always. As normal server - remove only if it is our primary router. Other connections - may be backup routers and these normal server don't handle here. */ - if (server->server_type != SILC_SERVER || - server->standalone || sock == SILC_PRIMARY_ROUTE(server)) { - /* Free all client entries that this server owns as they will - become invalid now as well. */ - silc_server_remove_clients_by_server(server, user_data, TRUE); - if (server->server_type == SILC_SERVER) - silc_server_remove_channels_by_server(server, user_data); - } + /* Remove all servers that are originated from this server, and + remove the clients of those servers too. */ + silc_server_remove_servers_by_server(server, user_data, TRUE); + + /* Remove the clients that this server owns as they will become + invalid now too. */ + silc_server_remove_clients_by_server(server, user_data, + user_data, TRUE); + + /* Remove channels owned by this server */ + if (server->server_type == SILC_SERVER) + silc_server_remove_channels_by_server(server, user_data); } else { - /* 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. */ + /* Enable local server connections that may be disabled */ silc_server_local_servers_toggle_enabled(server, TRUE); - silc_server_update_clients_by_server(server, user_data, backup_router, - TRUE, TRUE); + + /* If we are router and just lost our primary router (now standlaone) + we remove everything that was behind it, since we don't know + any better. */ + if (server->server_type == SILC_ROUTER && server->standalone) + /* Remove all servers that are originated from this server, and + remove the clients of those servers too. */ + silc_server_remove_servers_by_server(server, user_data, TRUE); + + /* Update the client entries of this server to the new backup + router. If we are the backup router we also resolve the real + servers for the clients. After updating is over this also + removes the clients that this server explicitly owns. */ + silc_server_update_clients_by_server(server, user_data, + backup_router, TRUE, TRUE); + + /* Update our server cache to use the new backup router too. */ 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, @@ -4828,8 +4840,6 @@ SILC_TASK_CALLBACK(silc_server_rekey_callback) SilcProtocol protocol; SilcServerRekeyInternalContext *proto_ctx; - SILC_LOG_DEBUG(("Start")); - /* Allocate internal protocol context. This is sent as context to the protocol. */ proto_ctx = silc_calloc(1, sizeof(*proto_ctx)); @@ -4847,6 +4857,8 @@ SILC_TASK_CALLBACK(silc_server_rekey_callback) /* Run the protocol */ silc_protocol_execute(protocol, server->schedule, 0, 0); + SILC_LOG_DEBUG(("Rekey protocol completed")); + /* Re-register re-key timeout */ silc_schedule_task_add(server->schedule, sock->sock, silc_server_rekey_callback, diff --git a/apps/silcd/server_backup.c b/apps/silcd/server_backup.c index 19b46784..5ec8945f 100644 --- a/apps/silcd/server_backup.c +++ b/apps/silcd/server_backup.c @@ -183,7 +183,7 @@ void silc_server_backup_replaced_add(SilcServer server, server->backup->replaced_count = 1; } - SILC_LOG_DEBUG(("Replacing router %s with %s backup", + SILC_LOG_DEBUG(("Replacing router %s with %s", silc_id_render(server_id, SILC_ID_SERVER), server_entry->server_name)); diff --git a/apps/silcd/server_util.c b/apps/silcd/server_util.c index 75091e94..89beb68a 100644 --- a/apps/silcd/server_util.c +++ b/apps/silcd/server_util.c @@ -39,11 +39,11 @@ silc_server_remove_clients_channels(SilcServer server, SilcChannelClientEntry chl, chl2; SilcHashTableList htl, htl2; - SILC_LOG_DEBUG(("Start")); - if (!client) return; + SILC_LOG_DEBUG(("Remove client from all channels")); + if (silc_hash_table_find(clients, client, NULL, NULL)) silc_hash_table_del(clients, client); @@ -119,13 +119,13 @@ silc_server_remove_clients_channels(SilcServer server, silc_hash_table_list_reset(&htl); } -/* This function is used to remove all client entries by the server `entry'. - This is called when the connection is lost to the server. In this case - we must invalidate all the client entries owned by the server `entry'. - If the `server_signoff' is TRUE then the SERVER_SIGNOFF notify is +/* This function removes all client entries that are originated from + `router' and are owned by `entry'. `router' and `entry' can be same + too. If `server_signoff' is TRUE then SERVER_SIGNOFF notify is distributed to our local clients. */ -bool silc_server_remove_clients_by_server(SilcServer server, +bool silc_server_remove_clients_by_server(SilcServer server, + SilcServerEntry router, SilcServerEntry entry, bool server_signoff) { @@ -143,7 +143,11 @@ bool silc_server_remove_clients_by_server(SilcServer server, if (!(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) return FALSE; - SILC_LOG_DEBUG(("Start")); + SILC_LOG_DEBUG(("Removing clients by %s", + entry->server_name ? entry->server_name : "server")); + + if (!router) + router = entry; /* Allocate the hash table that holds the channels that require channel key re-generation after we've removed this server's clients @@ -167,18 +171,15 @@ bool silc_server_remove_clients_by_server(SilcServer server, } if (silc_idcache_get_all(server->local_list->clients, &list)) { - if (silc_idcache_list_first(list, &id_cache)) { while (id_cache) { client = (SilcClientEntry)id_cache->context; - if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) { - if (!silc_idcache_list_next(list, &id_cache)) - break; - else - continue; - } - if (client->router != entry) { + /* If client is not registered, is not originated from `router' + or is not owned by `entry', skip it. */ + if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) || + client->router != router || + !SILC_ID_COMPARE(client->id, entry->id, client->id->ip.data_len)) { if (!silc_idcache_list_next(list, &id_cache)) break; else @@ -231,14 +232,12 @@ bool silc_server_remove_clients_by_server(SilcServer server, if (silc_idcache_list_first(list, &id_cache)) { while (id_cache) { client = (SilcClientEntry)id_cache->context; - if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) { - if (!silc_idcache_list_next(list, &id_cache)) - break; - else - continue; - } - - if (client->router != entry) { + + /* If client is not registered, is not originated from `router' + or is not owned by `entry', skip it. */ + if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) || + client->router != router || + !SILC_ID_COMPARE(client->id, entry->id, client->id->ip.data_len)) { if (!silc_idcache_list_next(list, &id_cache)) break; else @@ -290,8 +289,8 @@ bool silc_server_remove_clients_by_server(SilcServer server, if (server_signoff) { SilcBuffer args, not; - SILC_LOG_DEBUG(("Sending SERVER_SIGNOFF for %d clients", - argc - 1)); + SILC_LOG_DEBUG(("Sending SERVER_SIGNOFF for %s with %d clients", + silc_id_render(entry->id, SILC_ID_SERVER), argc - 1)); /* Send SERVER_SIGNOFF notify to our primary router */ if (server->router != entry) { @@ -614,7 +613,7 @@ void silc_server_update_clients_by_server(SilcServer server, /* Now remove the clients that are still marked as orignated from the `from'. These are the clients that really was owned by the `from' and not just exist behind the `from'. */ - silc_server_remove_clients_by_server(server, from, TRUE); + silc_server_remove_clients_by_server(server, from, from, TRUE); } /* Updates servers that are from `from' to be originated from `to'. This @@ -781,6 +780,79 @@ void silc_server_local_servers_toggle_enabled(SilcServer server, silc_idcache_list_free(list); } } + +/* Removes servers that are originated from the `from'. The server + entry is deleted in this function. If `remove_clients' is TRUE then + all clients originated from the server are removed too, and server + signoff is sent. Note that this does not remove the `from'. This + also does not remove locally connected servers. */ + +void silc_server_remove_servers_by_server(SilcServer server, + SilcServerEntry from, + bool remove_clients) +{ + SilcIDCacheList list = NULL; + SilcIDCacheEntry id_cache = NULL; + SilcServerEntry server_entry = NULL; + + SILC_LOG_DEBUG(("Removing servers by %s", + from->server_name ? from->server_name : "server")); + + 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 || + server_entry->router != from || server_entry == from) { + if (!silc_idcache_list_next(list, &id_cache)) + break; + else + continue; + } + + /* Remove clients owned by this server */ + if (remove_clients) + silc_server_remove_clients_by_server(server, from, server_entry, + TRUE); + + /* Remove the server */ + silc_idlist_del_server(server->local_list, server_entry); + + 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 || + server_entry->router != from || server_entry == from) { + if (!silc_idcache_list_next(list, &id_cache)) + break; + else + continue; + } + + /* Remove clients owned by this server */ + if (remove_clients) + silc_server_remove_clients_by_server(server, from, server_entry, + TRUE); + + /* Remove the server */ + silc_idlist_del_server(server->global_list, server_entry); + + if (!silc_idcache_list_next(list, &id_cache)) + break; + } + } + 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 6d906485..6831ce31 100644 --- a/apps/silcd/server_util.h +++ b/apps/silcd/server_util.h @@ -20,12 +20,12 @@ #ifndef SERVER_UTIL_H #define SERVER_UTIL_H -/* This function is used to remove all client entries by the server `entry'. - This is called when the connection is lost to the server. In this case - we must invalidate all the client entries owned by the server `entry'. - If the `server_signoff' is TRUE then the SERVER_SIGNOFF notify is +/* This function removes all client entries that are originated from + `router' and are owned by `entry'. `router' and `entry' can be same + too. If `server_signoff' is TRUE then SERVER_SIGNOFF notify is distributed to our local clients. */ -bool silc_server_remove_clients_by_server(SilcServer server, +bool silc_server_remove_clients_by_server(SilcServer server, + SilcServerEntry router, SilcServerEntry entry, bool server_signoff); @@ -57,6 +57,15 @@ void silc_server_update_servers_by_server(SilcServer server, void silc_server_local_servers_toggle_enabled(SilcServer server, bool toggle_enabled); +/* Removes servers that are originated from the `from'. The server + entry is deleted in this function. If `remove_clients' is TRUE then + all clients originated from the server are removed too, and server + signoff is sent. Note that this does not remove the `from'. This + also does not remove locally connected servers. */ +void silc_server_remove_servers_by_server(SilcServer server, + SilcServerEntry from, + bool remove_clients); + /* Removes channels that are from `from. */ void silc_server_remove_channels_by_server(SilcServer server, SilcServerEntry from); -- 2.24.0