+Thu Jul 5 21:22:32 EEST 2001 Pekka Riikonen <priikone@silcnet.org>
+
+ * Fixed a possible crash in silc_server_remove_clients_by_server
+ in silcd/server.c. Fixed there also some memory leaks.
+
+ * Fixed the silc_idlist_replace_client_id. It could replace
+ wrong key in the hash table. Affected file silcd/idlist.c.
+
+ * Do not check whether there are global users on the channel
+ if the channel->global_users is FALSE. Affected functions
+ silc_server_remove_from_one_channel and
+ silc_server_remove_from_channels in silcd/server.c. Also,
+ do not check if the removed client is local as we can be
+ sure that global client was not removed from the channel
+ and checking for global users is not needed.
+
+ * The silc_server_remove_clients_by_server now re-generates
+ the channel keys correctly for those channels that had
+ clients removed from them. Affected file silcd/server.c.
+
Tue Jul 3 11:39:20 EEST 2001 Pekka Riikonen <priikone@silcnet.org>
* Found the reason of random crashes in the server. We weren't
uint32 clients_c = 0;
unsigned char **argv = NULL;
uint32 *argv_lens = NULL, *argv_types = NULL, argc = 0;
+ SilcHashTable servers;
+ SilcChannelClientEntry chl;
+ SilcChannelEntry channel;
+ SilcHashTableList htl;
int i;
SILC_LOG_DEBUG(("Start"));
+ /* Allocate the hash table that holds the channels that require
+ channel key re-generation after we've removed this servers clients
+ from the channels. */
+ servers = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL,
+ NULL, NULL, TRUE);
+
if (server_signoff) {
idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) * (argc + 1));
argv_types = silc_realloc(argv_types, sizeof(*argv_types) * (argc + 1));
- argv[argc] = idp->data;
+ argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
+ memcpy(argv[argc], idp->data, idp->len);
argv_lens[argc] = idp->len;
argv_types[argc] = argc + 1;
argc++;
silc_buffer_free(idp);
}
+ silc_hash_table_list(client->channels, &htl);
+ while (silc_hash_table_get(&htl, NULL, (void *)&chl))
+ silc_hash_table_replace(servers, chl->channel, chl->channel);
+
/* Remove the client entry */
silc_server_remove_from_channels(server, NULL, client, FALSE,
NULL, FALSE);
silc_buffer_free(idp);
}
+ silc_hash_table_list(client->channels, &htl);
+ while (silc_hash_table_get(&htl, NULL, (void *)&chl))
+ silc_hash_table_replace(servers, chl->channel, chl->channel);
+
/* Remove the client entry */
silc_server_remove_from_channels(server, NULL, client, FALSE,
NULL, FALSE);
silc_free(clients);
silc_buffer_free(args);
+ for (i = 0; i < argc; i++)
+ silc_free(argv[i]);
silc_free(argv);
silc_free(argv_lens);
silc_free(argv_types);
}
+ /* We must now re-generate the channel key for all channels that had
+ this server's client(s) on the channel. As they left the channel we
+ must re-generate the channel key. */
+ silc_hash_table_list(servers, &htl);
+ while (silc_hash_table_get(&htl, NULL, (void *)&channel)) {
+ silc_server_create_channel_key(server, channel, 0);
+ silc_server_send_channel_key(server, NULL, channel,
+ server->server_type == SILC_ROUTER ?
+ FALSE : !server->standalone);
+ }
+ silc_hash_table_free(servers);
+
return TRUE;
}
server->stat.my_chanclients--;
/* If there is no global users on the channel anymore mark the channel
- as local channel. */
- if (server->server_type == SILC_SERVER &&
- !silc_server_channel_has_global(channel))
+ as local channel. Do not check if the removed client is local client. */
+ if (server->server_type == SILC_SERVER && channel->global_users &&
+ chl->client->router && !silc_server_channel_has_global(channel))
channel->global_users = FALSE;
/* If there is not at least one local user on the channel then we don't
server->stat.my_chanclients--;
/* If there is no global users on the channel anymore mark the channel
- as local channel. */
- if (server->server_type == SILC_SERVER &&
- !silc_server_channel_has_global(channel))
+ as local channel. Do not check if the client is local client. */
+ if (server->server_type == SILC_SERVER && channel->global_users &&
+ chl->client->router && !silc_server_channel_has_global(channel))
channel->global_users = FALSE;
/* If there is not at least one local user on the channel then we don't