and clients of those servers.
+Wed Jun 26 15:14:12 EEST 2002 Pekka Riikonen <priikone@silcnet.org>
+
+ * 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 <priikone@silcnet.org>
* Fixed a bug in silc_string_regexify which did not add '^'
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.
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 */
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;
}
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;
}
/* 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);
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;
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;
}
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) {
}
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,
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));
/* 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,
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));
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);
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)
{
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
}
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
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
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) {
/* 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
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,
#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);
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);