X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=apps%2Fsilcd%2Fserver_util.c;h=5c06bcd17f11abd582c0b083772f33e68f751a17;hb=9a85416f729ef965606a688fffb6baa9d22927a5;hp=b86abec99395c8b45fca87da86db8975b2567214;hpb=62cb7719f63ea3d3b7620533f5797dc7546b215a;p=silc.git diff --git a/apps/silcd/server_util.c b/apps/silcd/server_util.c index b86abec9..5c06bcd1 100644 --- a/apps/silcd/server_util.c +++ b/apps/silcd/server_util.c @@ -64,8 +64,8 @@ static void silc_server_remove_clients_channels(SilcServer server, if (silc_idlist_del_channel(server->local_list, channel)) server->stat.my_channels--; - else if (silc_idlist_del_channel(server->global_list, channel)) - server->stat.my_channels--; + else + silc_idlist_del_channel(server->global_list, channel); continue; } @@ -97,7 +97,7 @@ static void silc_server_remove_clients_channels(SilcServer server, SilcChannelClientEntry chl2; SilcHashTableList htl2; - channel->id = NULL; + channel->disabled = TRUE; silc_hash_table_list(channel->user_list, &htl2); while (silc_hash_table_get(&htl2, NULL, (void *)&chl2)) { @@ -105,14 +105,15 @@ static void silc_server_remove_clients_channels(SilcServer server, silc_hash_table_del(channel->user_list, chl2->client); silc_free(chl2); } + silc_hash_table_list_reset(&htl2); continue; } /* Remove the channel entry */ if (silc_idlist_del_channel(server->local_list, channel)) server->stat.my_channels--; - else if (silc_idlist_del_channel(server->global_list, channel)) - server->stat.my_channels--; + else + silc_idlist_del_channel(server->global_list, channel); continue; } @@ -121,6 +122,7 @@ static void silc_server_remove_clients_channels(SilcServer server, if (!silc_hash_table_find(channels, channel, NULL, NULL)) silc_hash_table_add(channels, channel, channel); } + silc_hash_table_list_reset(&htl); silc_buffer_free(clidp); } @@ -182,7 +184,7 @@ bool silc_server_remove_clients_by_server(SilcServer server, } if (client->router != entry) { - if (server_signoff && client->connection) { + if (server_signoff) { clients = silc_realloc(clients, sizeof(*clients) * (clients_c + 1)); clients[clients_c] = client; @@ -210,9 +212,21 @@ bool silc_server_remove_clients_by_server(SilcServer server, silc_buffer_free(idp); } + /* Update statistics */ + server->stat.clients--; + if (server->server_type == SILC_ROUTER) + server->stat.cell_clients--; + SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR); + SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR); + /* Remove the client entry */ silc_server_remove_clients_channels(server, NULL, client, channels); - silc_idlist_del_client(server->local_list, client); + if (!server_signoff) { + client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED; + id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF; + } else { + silc_idlist_del_client(server->local_list, client); + } if (!silc_idcache_list_next(list, &id_cache)) break; @@ -262,9 +276,21 @@ bool silc_server_remove_clients_by_server(SilcServer server, silc_buffer_free(idp); } + /* Update statistics */ + server->stat.clients--; + if (server->server_type == SILC_ROUTER) + server->stat.cell_clients--; + SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR); + SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR); + /* Remove the client entry */ silc_server_remove_clients_channels(server, NULL, client, channels); - silc_idlist_del_client(server->global_list, client); + if (!server_signoff) { + client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED; + id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF; + } else { + silc_idlist_del_client(server->global_list, client); + } if (!silc_idcache_list_next(list, &id_cache)) break; @@ -275,7 +301,7 @@ bool silc_server_remove_clients_by_server(SilcServer server, /* Send the SERVER_SIGNOFF notify */ if (server_signoff) { - SilcBuffer args; + SilcBuffer args, not; /* Send SERVER_SIGNOFF notify to our primary router */ if (!server->standalone && server->router && @@ -291,17 +317,19 @@ bool silc_server_remove_clients_by_server(SilcServer server, silc_buffer_free(args); } + /* Send to local clients. We also send the list of client ID's that + is to be removed for those servers that would like to use that list. */ args = silc_argument_payload_encode(argc, argv, argv_lens, argv_types); - /* Send to local clients */ - for (i = 0; i < clients_c; i++) { - silc_server_send_notify_args(server, clients[i]->connection, - FALSE, SILC_NOTIFY_TYPE_SERVER_SIGNOFF, - argc, args); - } + not = silc_notify_payload_encode_args(SILC_NOTIFY_TYPE_SERVER_SIGNOFF, + argc, args); + silc_server_packet_send_clients(server, clients, clients_c, + SILC_PACKET_NOTIFY, 0, FALSE, + not->data, not->len, FALSE); silc_free(clients); silc_buffer_free(args); + silc_buffer_free(not); for (i = 0; i < argc; i++) silc_free(argv[i]); silc_free(argv); @@ -314,8 +342,11 @@ bool silc_server_remove_clients_by_server(SilcServer server, must re-generate the channel key. */ silc_hash_table_list(channels, &htl); while (silc_hash_table_get(&htl, NULL, (void *)&channel)) { - if (!silc_server_create_channel_key(server, channel, 0)) + if (!silc_server_create_channel_key(server, channel, 0)) { + silc_hash_table_list_reset(&htl); + silc_hash_table_free(channels); return FALSE; + } /* Do not send the channel key if private channel key mode is set */ if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) @@ -325,6 +356,7 @@ bool silc_server_remove_clients_by_server(SilcServer server, server->server_type == SILC_ROUTER ? FALSE : !server->standalone); } + silc_hash_table_list_reset(&htl); silc_hash_table_free(channels); return TRUE; @@ -353,7 +385,6 @@ silc_server_update_clients_by_real_server(SilcServer server, SILC_LOG_DEBUG(("Found (local) %s", silc_id_render(server_entry->id, SILC_ID_SERVER))); -#if 0 if (!server_entry->data.send_key && server_entry->router) { SILC_LOG_DEBUG(("Server not locally connected, use its router")); /* If the client is not marked as local then move it to local list @@ -362,24 +393,21 @@ silc_server_update_clients_by_real_server(SilcServer server, SILC_LOG_DEBUG(("Moving client to local list")); silc_idcache_add(server->local_list->clients, client_cache->name, client_cache->id, client_cache->context, - client_cache->expire); + client_cache->expire, NULL); silc_idcache_del_by_context(server->global_list->clients, client); } server_entry = server_entry->router; } else { -#endif /* If the client is not marked as local then move it to local list since the server is local. */ if (server_entry->server_type != SILC_BACKUP_ROUTER && !local) { SILC_LOG_DEBUG(("Moving client to local list")); silc_idcache_add(server->local_list->clients, client_cache->name, client_cache->id, client_cache->context, - client_cache->expire); + client_cache->expire, NULL); silc_idcache_del_by_context(server->global_list->clients, client); } -#if 0 } -#endif silc_idcache_list_free(list); return server_entry; @@ -404,7 +432,6 @@ silc_server_update_clients_by_real_server(SilcServer server, SILC_LOG_DEBUG(("Found (global) %s", silc_id_render(server_entry->id, SILC_ID_SERVER))); -#if 0 if (!server_entry->data.send_key && server_entry->router) { SILC_LOG_DEBUG(("Server not locally connected, use its router")); /* If the client is marked as local then move it to global list @@ -413,24 +440,21 @@ silc_server_update_clients_by_real_server(SilcServer server, SILC_LOG_DEBUG(("Moving client to global list")); silc_idcache_add(server->global_list->clients, client_cache->name, client_cache->id, client_cache->context, - client_cache->expire); + client_cache->expire, NULL); silc_idcache_del_by_context(server->local_list->clients, client); } server_entry = server_entry->router; } else { -#endif /* If the client is marked as local then move it to global list since the server is global. */ if (server_entry->server_type != SILC_BACKUP_ROUTER && local) { SILC_LOG_DEBUG(("Moving client to global list")); silc_idcache_add(server->global_list->clients, client_cache->name, client_cache->id, client_cache->context, - client_cache->expire); + client_cache->expire, NULL); silc_idcache_del_by_context(server->local_list->clients, client); } -#if 0 } -#endif silc_idcache_list_free(list); return server_entry; @@ -480,8 +504,6 @@ void silc_server_update_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; @@ -529,7 +551,6 @@ void silc_server_update_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; @@ -623,6 +644,57 @@ void silc_server_update_servers_by_server(SilcServer server, } } +/* Removes channels that are from `from. */ + +void silc_server_remove_channels_by_server(SilcServer server, + SilcServerEntry from) +{ + SilcIDCacheList list = NULL; + SilcIDCacheEntry id_cache = NULL; + SilcChannelEntry channel = NULL; + + SILC_LOG_DEBUG(("Start")); + + if (silc_idcache_get_all(server->global_list->channels, &list)) { + if (silc_idcache_list_first(list, &id_cache)) { + while (id_cache) { + channel = (SilcChannelEntry)id_cache->context; + if (channel->router == from) + silc_idlist_del_channel(server->global_list, channel); + if (!silc_idcache_list_next(list, &id_cache)) + break; + } + } + silc_idcache_list_free(list); + } +} + +/* Updates channels that are from `from' to be originated from `to'. */ + +void silc_server_update_channels_by_server(SilcServer server, + SilcServerEntry from, + SilcServerEntry to) +{ + SilcIDCacheList list = NULL; + SilcIDCacheEntry id_cache = NULL; + SilcChannelEntry channel = NULL; + + SILC_LOG_DEBUG(("Start")); + + if (silc_idcache_get_all(server->global_list->channels, &list)) { + if (silc_idcache_list_first(list, &id_cache)) { + while (id_cache) { + channel = (SilcChannelEntry)id_cache->context; + if (channel->router == from) + channel->router = to; + if (!silc_idcache_list_next(list, &id_cache)) + break; + } + } + silc_idcache_list_free(list); + } +} + /* Checks whether given channel has global users. If it does this returns TRUE and FALSE if there is only locally connected clients on the channel. */ @@ -633,9 +705,12 @@ bool silc_server_channel_has_global(SilcChannelEntry channel) silc_hash_table_list(channel->user_list, &htl); while (silc_hash_table_get(&htl, NULL, (void *)&chl)) { - if (chl->client->router) + if (chl->client->router) { + silc_hash_table_list_reset(&htl); return TRUE; + } } + silc_hash_table_list_reset(&htl); return FALSE; } @@ -650,9 +725,12 @@ bool silc_server_channel_has_local(SilcChannelEntry channel) silc_hash_table_list(channel->user_list, &htl); while (silc_hash_table_get(&htl, NULL, (void *)&chl)) { - if (!chl->client->router) + if (!chl->client->router) { + silc_hash_table_list_reset(&htl); return TRUE; + } } + silc_hash_table_list_reset(&htl); return FALSE; } @@ -668,8 +746,44 @@ bool silc_server_client_on_channel(SilcClientEntry client, if (!client || !channel) return FALSE; - if (silc_hash_table_find(client->channels, channel, NULL, NULL)) - return TRUE; + return silc_hash_table_find(client->channels, channel, NULL, NULL); +} + +/* Checks string for bad characters and returns TRUE if they are found. */ + +bool silc_server_name_bad_chars(const char *name, uint32 name_len) +{ + int i; + + for (i = 0; i < name_len; i++) { + if (!isascii(name[i])) + return TRUE; + if (name[i] <= 32) return TRUE; + if (name[i] == ' ') return TRUE; + if (name[i] == '*') return TRUE; + if (name[i] == '?') return TRUE; + if (name[i] == ',') return TRUE; + } return FALSE; } + +/* Modifies the `name' if it includes bad characters and returns new + allocated name that does not include bad characters. */ + +char *silc_server_name_modify_bad(const char *name, uint32 name_len) +{ + int i; + char *newname = strdup(name); + + for (i = 0; i < name_len; i++) { + if (!isascii(newname[i])) newname[i] = '_'; + if (newname[i] <= 32) newname[i] = '_'; + if (newname[i] == ' ') newname[i] = '_'; + if (newname[i] == '*') newname[i] = '_'; + if (newname[i] == '?') newname[i] = '_'; + if (newname[i] == ',') newname[i] = '_'; + } + + return newname; +}