5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2002 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
21 #include "serverincludes.h"
22 #include "server_internal.h"
24 extern char *server_version;
26 /* Removes the client from channels and possibly removes the channels
27 as well. After removing those channels that exist, their channel
28 keys are regnerated. This is called only by the function
29 silc_server_remove_clients_by_server. */
32 silc_server_remove_clients_channels(SilcServer server,
33 SilcServerEntry server_entry,
34 SilcHashTable clients,
35 SilcClientEntry client,
36 SilcHashTable channels)
38 SilcChannelEntry channel;
39 SilcChannelClientEntry chl, chl2;
40 SilcHashTableList htl, htl2;
42 SILC_LOG_DEBUG(("Start"));
47 if (silc_hash_table_find(clients, client, NULL, NULL))
48 silc_hash_table_del(clients, client);
50 /* Remove the client from all channels. The client is removed from
51 the channels' user list. */
52 silc_hash_table_list(client->channels, &htl);
53 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
54 channel = chl->channel;
56 /* Remove channel if this is last client leaving the channel, unless
57 the channel is permanent. */
58 if (server->server_type == SILC_ROUTER &&
59 silc_hash_table_count(channel->user_list) < 2) {
60 if (silc_hash_table_find(channels, channel, NULL, NULL))
61 silc_hash_table_del(channels, channel);
62 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
63 silc_server_channel_delete(server, channel);
67 silc_hash_table_del(client->channels, channel);
68 silc_hash_table_del(channel->user_list, chl->client);
69 channel->user_count--;
71 /* If there is no global users on the channel anymore mark the channel
72 as local channel. Do not check if the removed client is local client. */
73 if (server->server_type != SILC_ROUTER && channel->global_users &&
74 chl->client->router && !silc_server_channel_has_global(channel))
75 channel->global_users = FALSE;
79 /* Update statistics */
80 if (SILC_IS_LOCAL(client))
81 server->stat.my_chanclients--;
82 if (server->server_type == SILC_ROUTER) {
83 server->stat.cell_chanclients--;
84 server->stat.chanclients--;
87 /* If there is not at least one local user on the channel then we don't
88 need the channel entry anymore, we can remove it safely, unless the
89 channel is permanent channel */
90 if (server->server_type != SILC_ROUTER &&
91 !silc_server_channel_has_local(channel)) {
92 if (silc_hash_table_find(channels, channel, NULL, NULL))
93 silc_hash_table_del(channels, channel);
94 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
95 silc_server_channel_delete(server, channel);
99 /* Mark other local clients to the table of clients whom will receive
100 the SERVER_SIGNOFF notify. */
101 silc_hash_table_list(channel->user_list, &htl2);
102 while (silc_hash_table_get(&htl2, NULL, (void **)&chl2)) {
103 SilcClientEntry c = chl2->client;
107 /* Add client to table, if it's not from the signoff server */
108 if (c->router != server_entry &&
109 !silc_hash_table_find(clients, c, NULL, NULL))
110 silc_hash_table_add(clients, c, c);
112 silc_hash_table_list_reset(&htl2);
114 /* Add the channel to the the channels list to regenerate the
116 if (!silc_hash_table_find(channels, channel, NULL, NULL))
117 silc_hash_table_add(channels, channel, channel);
119 silc_hash_table_list_reset(&htl);
122 /* This function is used to remove all client entries by the server `entry'.
123 This is called when the connection is lost to the server. In this case
124 we must invalidate all the client entries owned by the server `entry'.
125 If the `server_signoff' is TRUE then the SERVER_SIGNOFF notify is
126 distributed to our local clients. */
128 bool silc_server_remove_clients_by_server(SilcServer server,
129 SilcServerEntry entry,
132 SilcIDCacheList list = NULL;
133 SilcIDCacheEntry id_cache = NULL;
134 SilcClientEntry client = NULL;
136 unsigned char **argv = NULL;
137 SilcUInt32 *argv_lens = NULL, *argv_types = NULL, argc = 0;
138 SilcHashTableList htl;
139 SilcChannelEntry channel;
140 SilcHashTable channels, clients;
143 SILC_LOG_DEBUG(("Start"));
145 /* Allocate the hash table that holds the channels that require
146 channel key re-generation after we've removed this server's clients
147 from the channels. */
148 channels = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL,
150 clients = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL,
153 if (server_signoff) {
154 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
155 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
156 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) * (argc + 1));
157 argv_types = silc_realloc(argv_types, sizeof(*argv_types) * (argc + 1));
158 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
159 memcpy(argv[argc], idp->data, idp->len);
160 argv_lens[argc] = idp->len;
161 argv_types[argc] = argc + 1;
163 silc_buffer_free(idp);
166 if (silc_idcache_get_all(server->local_list->clients, &list)) {
168 if (silc_idcache_list_first(list, &id_cache)) {
170 client = (SilcClientEntry)id_cache->context;
171 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
172 if (!silc_idcache_list_next(list, &id_cache))
178 if (client->router != entry) {
179 if (!silc_idcache_list_next(list, &id_cache))
185 if (server_signoff) {
186 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
187 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
188 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
190 argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
192 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
193 memcpy(argv[argc], idp->data, idp->len);
194 argv_lens[argc] = idp->len;
195 argv_types[argc] = argc + 1;
197 silc_buffer_free(idp);
200 /* Update statistics */
201 server->stat.clients--;
202 if (server->stat.cell_clients)
203 server->stat.cell_clients--;
204 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
205 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
207 silc_server_remove_clients_channels(server, entry, clients,
209 silc_server_del_from_watcher_list(server, client);
211 /* Remove the client entry */
212 if (!server_signoff) {
213 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
214 id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
216 silc_idlist_del_client(server->local_list, client);
219 if (!silc_idcache_list_next(list, &id_cache))
223 silc_idcache_list_free(list);
226 if (silc_idcache_get_all(server->global_list->clients, &list)) {
228 if (silc_idcache_list_first(list, &id_cache)) {
230 client = (SilcClientEntry)id_cache->context;
231 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
232 if (!silc_idcache_list_next(list, &id_cache))
238 if (client->router != entry) {
239 if (!silc_idcache_list_next(list, &id_cache))
245 if (server_signoff) {
246 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
247 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
248 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
250 argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
252 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
253 memcpy(argv[argc], idp->data, idp->len);
254 argv_lens[argc] = idp->len;
255 argv_types[argc] = argc + 1;
257 silc_buffer_free(idp);
260 /* Update statistics */
261 server->stat.clients--;
262 if (server->stat.cell_clients)
263 server->stat.cell_clients--;
264 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
265 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
267 silc_server_remove_clients_channels(server, entry, clients,
269 silc_server_del_from_watcher_list(server, client);
271 /* Remove the client entry */
272 if (!server_signoff) {
273 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
274 id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
276 silc_idlist_del_client(server->global_list, client);
279 if (!silc_idcache_list_next(list, &id_cache))
283 silc_idcache_list_free(list);
286 /* Send the SERVER_SIGNOFF notify */
287 if (server_signoff) {
288 SilcBuffer args, not;
290 SILC_LOG_DEBUG(("Sending SERVER_SIGNOFF for %d clients",
293 /* Send SERVER_SIGNOFF notify to our primary router */
294 if (server->router != entry) {
295 args = silc_argument_payload_encode(1, argv, argv_lens,
297 silc_server_send_notify_args(server, SILC_PRIMARY_ROUTE(server),
298 SILC_BROADCAST(server),
299 SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
301 silc_buffer_free(args);
304 /* Send to local clients. We also send the list of client ID's that
305 is to be removed for those servers that would like to use that list. */
306 args = silc_argument_payload_encode(argc, argv, argv_lens,
308 not = silc_notify_payload_encode_args(SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
310 silc_server_packet_send_clients(server, clients,
311 SILC_PACKET_NOTIFY, 0, FALSE,
312 not->data, not->len, FALSE);
314 silc_buffer_free(args);
315 silc_buffer_free(not);
316 for (i = 0; i < argc; i++)
319 silc_free(argv_lens);
320 silc_free(argv_types);
321 silc_hash_table_free(clients);
324 /* We must now re-generate the channel key for all channels that had
325 this server's client(s) on the channel. As they left the channel we
326 must re-generate the channel key. */
327 silc_hash_table_list(channels, &htl);
328 while (silc_hash_table_get(&htl, NULL, (void **)&channel)) {
329 if (!silc_server_create_channel_key(server, channel, 0)) {
330 silc_hash_table_list_reset(&htl);
331 silc_hash_table_free(channels);
335 /* Do not send the channel key if private channel key mode is set */
336 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY)
339 silc_server_send_channel_key(server, NULL, channel,
340 server->server_type == SILC_ROUTER ?
341 FALSE : !server->standalone);
343 silc_hash_table_list_reset(&htl);
344 silc_hash_table_free(channels);
349 static SilcServerEntry
350 silc_server_update_clients_by_real_server(SilcServer server,
351 SilcServerEntry from,
352 SilcClientEntry client,
354 SilcIDCacheEntry client_cache)
356 SilcServerEntry server_entry;
357 SilcIDCacheEntry id_cache = NULL;
358 SilcIDCacheList list;
360 if (!silc_idcache_get_all(server->local_list->servers, &list))
363 if (silc_idcache_list_first(list, &id_cache)) {
365 server_entry = (SilcServerEntry)id_cache->context;
366 if (server_entry != from &&
367 SILC_ID_COMPARE(server_entry->id, client->id,
368 client->id->ip.data_len)) {
369 SILC_LOG_DEBUG(("Found (local) %s",
370 silc_id_render(server_entry->id, SILC_ID_SERVER)));
372 if (!server_entry->data.send_key && server_entry->router) {
373 SILC_LOG_DEBUG(("Server not locally connected, use its router"));
374 /* If the client is not marked as local then move it to local list
375 since the server is local. */
377 SILC_LOG_DEBUG(("Moving client to local list"));
378 silc_idcache_add(server->local_list->clients, client_cache->name,
379 client_cache->id, client_cache->context,
380 client_cache->expire, NULL);
381 silc_idcache_del_by_context(server->global_list->clients, client);
383 server_entry = server_entry->router;
385 /* If the client is not marked as local then move it to local list
386 since the server is local. */
387 if (server_entry->server_type != SILC_BACKUP_ROUTER && !local) {
388 SILC_LOG_DEBUG(("Moving client to local list"));
389 silc_idcache_add(server->local_list->clients, client_cache->name,
390 client_cache->id, client_cache->context,
391 client_cache->expire, NULL);
392 silc_idcache_del_by_context(server->global_list->clients, client);
396 silc_idcache_list_free(list);
400 if (!silc_idcache_list_next(list, &id_cache))
405 silc_idcache_list_free(list);
407 if (!silc_idcache_get_all(server->global_list->servers, &list))
410 if (silc_idcache_list_first(list, &id_cache)) {
412 server_entry = (SilcServerEntry)id_cache->context;
413 if (server_entry != from &&
414 SILC_ID_COMPARE(server_entry->id, client->id,
415 client->id->ip.data_len)) {
416 SILC_LOG_DEBUG(("Found (global) %s",
417 silc_id_render(server_entry->id, SILC_ID_SERVER)));
419 if (!server_entry->data.send_key && server_entry->router) {
420 SILC_LOG_DEBUG(("Server not locally connected, use its router"));
421 /* If the client is marked as local then move it to global list
422 since the server is global. */
424 SILC_LOG_DEBUG(("Moving client to global list"));
425 silc_idcache_add(server->global_list->clients, client_cache->name,
426 client_cache->id, client_cache->context,
427 client_cache->expire, NULL);
428 silc_idcache_del_by_context(server->local_list->clients, client);
430 server_entry = server_entry->router;
432 /* If the client is marked as local then move it to global list
433 since the server is global. */
434 if (server_entry->server_type != SILC_BACKUP_ROUTER && local) {
435 SILC_LOG_DEBUG(("Moving client to global list"));
436 silc_idcache_add(server->global_list->clients, client_cache->name,
437 client_cache->id, client_cache->context,
438 client_cache->expire, NULL);
439 silc_idcache_del_by_context(server->local_list->clients, client);
443 silc_idcache_list_free(list);
447 if (!silc_idcache_list_next(list, &id_cache))
452 silc_idcache_list_free(list);
457 /* Updates the clients that are originated from the `from' to be originated
458 from the `to'. If the `resolve_real_server' is TRUE then this will
459 attempt to figure out which clients really are originated from the
460 `from' and which are originated from a server that we have connection
461 to, when we've acting as backup router. If it is FALSE the `to' will
462 be the new source. This function also removes the clients that are
463 *really* originated from `from' if `remove_from' is TRUE. These are
464 clients that the `from' owns, and not just clients that are behind
465 the `from'. If `from' is NULL then all non-local clients are switched
468 void silc_server_update_clients_by_server(SilcServer server,
469 SilcServerEntry from,
471 bool resolve_real_server,
474 SilcIDCacheList list = NULL;
475 SilcIDCacheEntry id_cache = NULL;
476 SilcClientEntry client = NULL;
479 SILC_LOG_DEBUG(("Start"));
482 SILC_LOG_DEBUG(("Updating %s", silc_id_render(from->id,
485 SILC_LOG_DEBUG(("to %s", silc_id_render(to->id,
489 if (silc_idcache_get_all(server->global_list->clients, &list)) {
490 if (silc_idcache_list_first(list, &id_cache)) {
492 client = (SilcClientEntry)id_cache->context;
494 /* If entry is disabled skip it. If entry is local to us, do not
495 switch it to anyone else, it is ours so skip it. */
496 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
497 SILC_IS_LOCAL(client)) {
498 if (!silc_idcache_list_next(list, &id_cache))
504 SILC_LOG_DEBUG(("Client (global) %s",
505 silc_id_render(client->id, SILC_ID_CLIENT)));
507 SILC_LOG_DEBUG(("Client->router (global) %s",
508 silc_id_render(client->router->id, SILC_ID_SERVER)));
511 if (client->router == from) {
512 /* Skip clients that are *really* owned by the `from' */
513 if (remove_from && SILC_ID_COMPARE(from->id, client->id,
514 client->id->ip.data_len)) {
515 SILC_LOG_DEBUG(("Found really owned client, skip it"));
516 if (!silc_idcache_list_next(list, &id_cache))
522 if (resolve_real_server) {
524 silc_server_update_clients_by_real_server(server, from, client,
533 /* All are changed */
537 if (!silc_idcache_list_next(list, &id_cache))
541 silc_idcache_list_free(list);
545 if (silc_idcache_get_all(server->local_list->clients, &list)) {
546 if (silc_idcache_list_first(list, &id_cache)) {
548 client = (SilcClientEntry)id_cache->context;
550 /* If entry is disabled skip it. If entry is local to us, do not
551 switch it to anyone else, it is ours so skip it. */
552 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
553 SILC_IS_LOCAL(client)) {
554 if (!silc_idcache_list_next(list, &id_cache))
560 SILC_LOG_DEBUG(("Client (local) %s",
561 silc_id_render(client->id, SILC_ID_CLIENT)));
563 SILC_LOG_DEBUG(("Client->router (local) %s",
564 silc_id_render(client->router->id, SILC_ID_SERVER)));
567 if (client->router == from) {
568 /* Skip clients that are *really* owned by the `from' */
569 if (remove_from && SILC_ID_COMPARE(from->id, client->id,
570 client->id->ip.data_len)) {
571 SILC_LOG_DEBUG(("Found really owned client, skip it"));
572 if (!silc_idcache_list_next(list, &id_cache))
578 if (resolve_real_server) {
580 silc_server_update_clients_by_real_server(server, from, client,
583 client->router = from; /* on local list put old from */
589 /* All are changed */
593 if (!silc_idcache_list_next(list, &id_cache))
597 silc_idcache_list_free(list);
601 /* Now remove the clients that are still marked as orignated from the
602 `from'. These are the clients that really was owned by the `from' and
603 not just exist behind the `from'. */
604 silc_server_remove_clients_by_server(server, from, TRUE);
607 /* Updates servers that are from `from' to be originated from `to'. This
608 will also update the server's connection to `to's connection. If
609 `local_toggle_enabled' is TRUE then local server's connections are
610 enabled, if FALSE they are disabled. */
612 void silc_server_update_servers_by_server(SilcServer server,
613 SilcServerEntry from,
615 bool local_toggle_enabled)
617 SilcIDCacheList list = NULL;
618 SilcIDCacheEntry id_cache = NULL;
619 SilcServerEntry server_entry = NULL;
621 if (silc_idcache_get_all(server->local_list->servers, &list)) {
622 if (silc_idcache_list_first(list, &id_cache)) {
624 server_entry = (SilcServerEntry)id_cache->context;
626 if (SILC_IS_LOCAL(server_entry)) {
627 if (server_entry != server->id_entry) {
628 if (local_toggle_enabled)
629 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
631 server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
634 /* If entry is local to us, do not switch it to any oneelse,
636 if (!silc_idcache_list_next(list, &id_cache))
642 if (server_entry->router == from) {
643 SILC_LOG_DEBUG(("Updating server (local) %s",
644 server_entry->server_name ?
645 server_entry->server_name : ""));
646 server_entry->router = to;
647 server_entry->connection = to->connection;
650 if (!silc_idcache_list_next(list, &id_cache))
654 silc_idcache_list_free(list);
657 if (silc_idcache_get_all(server->global_list->servers, &list)) {
658 if (silc_idcache_list_first(list, &id_cache)) {
660 server_entry = (SilcServerEntry)id_cache->context;
662 if (SILC_IS_LOCAL(server_entry)) {
663 if (server_entry != server->id_entry) {
664 if (local_toggle_enabled)
665 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
667 server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
670 /* If entry is local to us, do not switch it to anyone else,
672 if (!silc_idcache_list_next(list, &id_cache))
678 if (server_entry->router == from) {
679 SILC_LOG_DEBUG(("Updating server (global) %s",
680 server_entry->server_name ?
681 server_entry->server_name : ""));
682 server_entry->router = to;
683 server_entry->connection = to->connection;
686 if (!silc_idcache_list_next(list, &id_cache))
690 silc_idcache_list_free(list);
694 /* Removes channels that are from `from. */
696 void silc_server_remove_channels_by_server(SilcServer server,
697 SilcServerEntry from)
699 SilcIDCacheList list = NULL;
700 SilcIDCacheEntry id_cache = NULL;
701 SilcChannelEntry channel = NULL;
703 SILC_LOG_DEBUG(("Removing channels by server"));
705 if (silc_idcache_get_all(server->global_list->channels, &list)) {
706 if (silc_idcache_list_first(list, &id_cache)) {
708 channel = (SilcChannelEntry)id_cache->context;
709 if (channel->router == from)
710 silc_idlist_del_channel(server->global_list, channel);
711 if (!silc_idcache_list_next(list, &id_cache))
715 silc_idcache_list_free(list);
719 /* Updates channels that are from `from' to be originated from `to'. */
721 void silc_server_update_channels_by_server(SilcServer server,
722 SilcServerEntry from,
725 SilcIDCacheList list = NULL;
726 SilcIDCacheEntry id_cache = NULL;
727 SilcChannelEntry channel = NULL;
729 SILC_LOG_DEBUG(("Updating channels by server"));
731 if (silc_idcache_get_all(server->global_list->channels, &list)) {
732 if (silc_idcache_list_first(list, &id_cache)) {
734 channel = (SilcChannelEntry)id_cache->context;
735 if (channel->router == from)
736 channel->router = to;
737 if (!silc_idcache_list_next(list, &id_cache))
741 silc_idcache_list_free(list);
745 /* Checks whether given channel has global users. If it does this returns
746 TRUE and FALSE if there is only locally connected clients on the channel. */
748 bool silc_server_channel_has_global(SilcChannelEntry channel)
750 SilcChannelClientEntry chl;
751 SilcHashTableList htl;
753 silc_hash_table_list(channel->user_list, &htl);
754 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
755 if (chl->client->router) {
756 silc_hash_table_list_reset(&htl);
760 silc_hash_table_list_reset(&htl);
765 /* Checks whether given channel has locally connected users. If it does this
766 returns TRUE and FALSE if there is not one locally connected client. */
768 bool silc_server_channel_has_local(SilcChannelEntry channel)
770 SilcChannelClientEntry chl;
771 SilcHashTableList htl;
773 silc_hash_table_list(channel->user_list, &htl);
774 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
775 if (!chl->client->router) {
776 silc_hash_table_list_reset(&htl);
780 silc_hash_table_list_reset(&htl);
785 /* This function removes the channel and all users on the channel, unless
786 the channel is permanent. In this case the channel is disabled but all
787 users are removed from the channel. Returns TRUE if the channel is
788 destroyed totally, and FALSE if it is permanent and remains. */
790 bool silc_server_channel_delete(SilcServer server,
791 SilcChannelEntry channel)
793 SilcChannelClientEntry chl;
794 SilcHashTableList htl;
795 bool delchan = !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH);
798 SILC_LOG_DEBUG(("Deleting %s channel", channel->channel_name));
800 /* Update statistics */
801 if (server->server_type == SILC_ROUTER)
802 server->stat.chanclients -= channel->user_count;
804 /* Totally delete the channel and all users on the channel. The
805 users are deleted automatically in silc_idlist_del_channel. */
806 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
807 if (silc_idlist_del_channel(server->local_list, channel)) {
808 server->stat.my_channels--;
809 if (server->server_type == SILC_ROUTER) {
810 server->stat.channels--;
811 server->stat.cell_channels--;
814 if (silc_idlist_del_channel(server->global_list, channel))
815 if (server->server_type == SILC_ROUTER)
816 server->stat.channels--;
822 /* Channel is permanent, do not remove it, remove only users */
823 channel->disabled = TRUE;
824 silc_hash_table_list(channel->user_list, &htl);
825 while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
826 silc_hash_table_del(chl->client->channels, channel);
827 silc_hash_table_del(channel->user_list, chl->client);
828 channel->user_count--;
830 /* Update statistics */
831 if (SILC_IS_LOCAL(chl->client))
832 server->stat.my_chanclients--;
833 if (server->server_type == SILC_ROUTER) {
834 server->stat.cell_chanclients--;
835 server->stat.chanclients--;
840 silc_hash_table_list_reset(&htl);
842 SILC_LOG_DEBUG(("Channel %s remains", channel->channel_name));
847 /* Returns TRUE if the given client is on the channel. FALSE if not.
848 This works because we assure that the user list on the channel is
849 always in up to date thus we can only check the channel list from
850 `client' which is faster than checking the user list from `channel'. */
852 bool silc_server_client_on_channel(SilcClientEntry client,
853 SilcChannelEntry channel,
854 SilcChannelClientEntry *chl)
856 if (!client || !channel)
859 return silc_hash_table_find(client->channels, channel, NULL,
863 /* Checks string for bad characters and returns TRUE if they are found. */
865 bool silc_server_name_bad_chars(const char *name, SilcUInt32 name_len)
869 for (i = 0; i < name_len; i++) {
870 if (!isascii(name[i]))
872 if (name[i] <= 32) return TRUE;
873 if (name[i] == ' ') return TRUE;
874 if (name[i] == '*') return TRUE;
875 if (name[i] == '?') return TRUE;
876 if (name[i] == ',') return TRUE;
882 /* Modifies the `name' if it includes bad characters and returns new
883 allocated name that does not include bad characters. */
885 char *silc_server_name_modify_bad(const char *name, SilcUInt32 name_len)
888 char *newname = strdup(name);
890 for (i = 0; i < name_len; i++) {
891 if (!isascii(newname[i])) newname[i] = '_';
892 if (newname[i] <= 32) newname[i] = '_';
893 if (newname[i] == ' ') newname[i] = '_';
894 if (newname[i] == '*') newname[i] = '_';
895 if (newname[i] == '?') newname[i] = '_';
896 if (newname[i] == ',') newname[i] = '_';
902 /* Find number of sockets by IP address indicated by `ip'. Returns 0 if
903 socket connections with the IP address does not exist. */
905 SilcUInt32 silc_server_num_sockets_by_ip(SilcServer server, const char *ip,
910 for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
911 if (server->sockets[i] && !strcmp(server->sockets[i]->ip, ip) &&
912 server->sockets[i]->type == type)
919 /* Find number of sockets by IP address indicated by remote host, indicatd
920 by `ip' or `hostname', `port', and `type'. Returns 0 if socket connections
921 does not exist. If `ip' is provided then `hostname' is ignored. */
923 SilcUInt32 silc_server_num_sockets_by_remote(SilcServer server,
925 const char *hostname,
931 if (!ip && !hostname)
934 for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
935 if (server->sockets[i] &&
936 ((ip && !strcmp(server->sockets[i]->ip, ip)) ||
937 (hostname && !strcmp(server->sockets[i]->hostname, hostname))) &&
938 server->sockets[i]->port == port &&
939 server->sockets[i]->type == type)
946 /* Finds locally cached public key by the public key received in the SKE.
947 If we have it locally cached then we trust it and will use it in the
948 authentication protocol. Returns the locally cached public key or NULL
949 if we do not find the public key. */
951 SilcPublicKey silc_server_find_public_key(SilcServer server,
952 SilcHashTable local_public_keys,
953 SilcPublicKey remote_public_key)
955 SilcPublicKey cached_key;
957 SILC_LOG_DEBUG(("Find remote public key (%d keys in local cache)",
958 silc_hash_table_count(local_public_keys)));
960 if (!silc_hash_table_find_ext(local_public_keys, remote_public_key,
961 (void **)&cached_key, NULL,
962 silc_hash_public_key, NULL,
963 silc_hash_public_key_compare, NULL)) {
964 SILC_LOG_ERROR(("Public key not found"));
968 SILC_LOG_DEBUG(("Found public key"));
973 /* This returns the first public key from the table of public keys. This
974 is used only in cases where single public key exists in the table and
975 we want to get a pointer to it. For public key tables that has multiple
976 keys in it the silc_server_find_public_key must be used. */
978 SilcPublicKey silc_server_get_public_key(SilcServer server,
979 SilcHashTable local_public_keys)
981 SilcPublicKey cached_key;
982 SilcHashTableList htl;
984 SILC_LOG_DEBUG(("Start"));
986 assert(silc_hash_table_count(local_public_keys) < 2);
988 silc_hash_table_list(local_public_keys, &htl);
989 if (!silc_hash_table_get(&htl, NULL, (void **)&cached_key))
991 silc_hash_table_list_reset(&htl);
996 /* Check whether the connection `sock' is allowed to connect to us. This
997 checks for example whether there is too much connections for this host,
998 and required version for the host etc. */
1000 bool silc_server_connection_allowed(SilcServer server,
1001 SilcSocketConnection sock,
1002 SilcSocketType type,
1003 SilcServerConfigConnParams *global,
1004 SilcServerConfigConnParams *params,
1007 SilcUInt32 conn_number = (type == SILC_SOCKET_TYPE_CLIENT ?
1008 server->stat.my_clients :
1009 type == SILC_SOCKET_TYPE_SERVER ?
1010 server->stat.my_servers :
1011 server->stat.my_routers);
1012 SilcUInt32 num_sockets, max_hosts, max_per_host;
1013 SilcUInt32 r_protocol_version, l_protocol_version;
1014 SilcUInt32 r_software_version, l_software_version;
1015 char *r_vendor_version = NULL, *l_vendor_version;
1017 SILC_LOG_DEBUG(("Checking whether connection is allowed"));
1021 l_protocol_version =
1022 silc_version_to_num(params && params->version_protocol ?
1023 params->version_protocol :
1024 global->version_protocol);
1025 l_software_version =
1026 silc_version_to_num(params && params->version_software ?
1027 params->version_software :
1028 global->version_software);
1029 l_vendor_version = (params && params->version_software_vendor ?
1030 params->version_software_vendor :
1031 global->version_software_vendor);
1033 if (ske && silc_ske_parse_version(ske, &r_protocol_version, NULL,
1034 &r_software_version, NULL,
1035 &r_vendor_version)) {
1036 sock->version = r_protocol_version;
1038 /* Match protocol version */
1039 if (l_protocol_version && r_protocol_version &&
1040 r_protocol_version < l_protocol_version) {
1041 SILC_LOG_INFO(("Connection %s (%s) is too old version",
1042 sock->hostname, sock->ip));
1043 silc_server_disconnect_remote(server, sock,
1044 SILC_STATUS_ERR_BAD_VERSION,
1045 "You support too old protocol version");
1049 /* Math software version */
1050 if (l_software_version && r_software_version &&
1051 r_software_version < l_software_version) {
1052 SILC_LOG_INFO(("Connection %s (%s) is too old version",
1053 sock->hostname, sock->ip));
1054 silc_server_disconnect_remote(server, sock,
1055 SILC_STATUS_ERR_BAD_VERSION,
1056 "You support too old software version");
1060 /* Regex match vendor version */
1061 if (l_vendor_version && r_vendor_version &&
1062 !silc_string_match(l_vendor_version, r_vendor_version)) {
1063 SILC_LOG_INFO(("Connection %s (%s) is unsupported version",
1064 sock->hostname, sock->ip));
1065 silc_server_disconnect_remote(server, sock,
1066 SILC_STATUS_ERR_BAD_VERSION,
1067 "Your software is not supported");
1071 silc_free(r_vendor_version);
1073 /* Check for maximum connections limit */
1075 num_sockets = silc_server_num_sockets_by_ip(server, sock->ip, type);
1076 max_hosts = (params ? params->connections_max : global->connections_max);
1077 max_per_host = (params ? params->connections_max_per_host :
1078 global->connections_max_per_host);
1080 if (max_hosts && conn_number >= max_hosts) {
1081 SILC_LOG_INFO(("Server is full, closing %s (%s) connection",
1082 sock->hostname, sock->ip));
1083 silc_server_disconnect_remote(server, sock,
1084 SILC_STATUS_ERR_RESOURCE_LIMIT,
1085 "Server is full, try again later");
1089 if (num_sockets >= max_per_host) {
1090 SILC_LOG_INFO(("Too many connections from %s (%s), closing connection",
1091 sock->hostname, sock->ip));
1092 silc_server_disconnect_remote(server, sock,
1093 SILC_STATUS_ERR_RESOURCE_LIMIT,
1094 "Too many connections from your host");
1101 /* Checks that client has rights to add or remove channel modes. If any
1102 of the checks fails FALSE is returned. */
1104 bool silc_server_check_cmode_rights(SilcServer server,
1105 SilcChannelEntry channel,
1106 SilcChannelClientEntry client,
1109 bool is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1110 bool is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1112 /* Check whether has rights to change anything */
1113 if (!is_op && !is_fo)
1116 /* Check whether has rights to change everything */
1120 /* Founder implies operator */
1124 /* We know that client is channel operator, check that they are not
1125 changing anything that requires channel founder rights. Rest of the
1126 modes are available automatically for channel operator. */
1128 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1129 if (is_op && !is_fo)
1132 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1133 if (is_op && !is_fo)
1138 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1139 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
1140 if (is_op && !is_fo)
1144 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1145 if (is_op && !is_fo)
1150 if (mode & SILC_CHANNEL_MODE_CIPHER) {
1151 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
1152 if (is_op && !is_fo)
1156 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1157 if (is_op && !is_fo)
1162 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1163 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
1164 if (is_op && !is_fo)
1168 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1169 if (is_op && !is_fo)
1174 if (mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1175 if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS)) {
1176 if (is_op && !is_fo)
1180 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1181 if (is_op && !is_fo)
1186 if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1187 if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS)) {
1188 if (is_op && !is_fo)
1192 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1193 if (is_op && !is_fo)
1201 /* Check that the client has rights to change its user mode. Returns
1202 FALSE if setting some mode is not allowed. */
1204 bool silc_server_check_umode_rights(SilcServer server,
1205 SilcClientEntry client,
1208 bool server_op = FALSE, router_op = FALSE;
1210 if (mode & SILC_UMODE_SERVER_OPERATOR) {
1211 /* Cannot set server operator mode (must use OPER command) */
1212 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR))
1215 /* Remove the server operator rights */
1216 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
1220 if (mode & SILC_UMODE_ROUTER_OPERATOR) {
1221 /* Cannot set router operator mode (must use SILCOPER command) */
1222 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR))
1225 /* Remove the router operator rights */
1226 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
1231 SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR);
1233 SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR);
1238 /* This function is used to send the notify packets and motd to the
1239 incoming client connection. */
1241 void silc_server_send_connect_notifys(SilcServer server,
1242 SilcSocketConnection sock,
1243 SilcClientEntry client)
1245 SilcIDListData idata = (SilcIDListData)client;
1247 SILC_LOG_DEBUG(("Send welcome notifys"));
1249 /* Send some nice info to the client */
1250 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1251 ("Welcome to the SILC Network %s",
1253 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1254 ("Your host is %s, running version %s",
1255 server->server_name, server_version));
1257 if (server->server_type == SILC_ROUTER) {
1258 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1259 ("There are %d clients, %d servers and %d "
1260 "routers in SILC Network",
1261 server->stat.clients, server->stat.servers + 1,
1262 server->stat.routers));
1264 if (server->stat.clients && server->stat.servers + 1)
1265 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1266 ("There are %d clients, %d servers and %d "
1267 "routers in SILC Network",
1268 server->stat.clients, server->stat.servers + 1,
1269 (server->standalone ? 0 :
1270 !server->stat.routers ? 1 :
1271 server->stat.routers)));
1274 if (server->stat.cell_clients && server->stat.cell_servers + 1)
1275 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1276 ("There are %d clients on %d server in our cell",
1277 server->stat.cell_clients,
1278 server->stat.cell_servers + 1));
1279 if (server->server_type == SILC_ROUTER) {
1280 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1281 ("I have %d clients, %d channels, %d servers and "
1283 server->stat.my_clients,
1284 server->stat.my_channels,
1285 server->stat.my_servers,
1286 server->stat.my_routers));
1288 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1289 ("I have %d clients and %d channels formed",
1290 server->stat.my_clients,
1291 server->stat.my_channels));
1294 if (server->stat.server_ops || server->stat.router_ops)
1295 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1296 ("There are %d server operators and %d router "
1298 server->stat.server_ops,
1299 server->stat.router_ops));
1300 if (server->stat.my_router_ops + server->stat.my_server_ops)
1301 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1302 ("I have %d operators online",
1303 server->stat.my_router_ops +
1304 server->stat.my_server_ops));
1306 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1307 ("Your connection is secured with %s cipher, "
1308 "key length %d bits",
1309 idata->send_key->cipher->name,
1310 idata->send_key->cipher->key_len));
1311 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1312 ("Your current nickname is %s",
1316 silc_server_send_motd(server, sock);
1319 /* Kill the client indicated by `remote_client' sending KILLED notify
1320 to the client, to all channels client has joined and to primary
1321 router if needed. The killed client is also removed from all channels. */
1323 void silc_server_kill_client(SilcServer server,
1324 SilcClientEntry remote_client,
1325 const char *comment,
1327 SilcIdType killer_id_type)
1329 SilcBuffer killed, killer;
1331 SILC_LOG_DEBUG(("Killing client %s",
1332 silc_id_render(remote_client->id, SILC_ID_CLIENT)));
1334 /* Send the KILL notify packets. First send it to the channel, then
1335 to our primary router and then directly to the client who is being
1336 killed right now. */
1338 killed = silc_id_payload_encode(remote_client->id, SILC_ID_CLIENT);
1339 killer = silc_id_payload_encode(killer_id, killer_id_type);
1341 /* Send KILLED notify to the channels. It is not sent to the client
1342 as it will be sent differently destined directly to the client and not
1344 silc_server_send_notify_on_channels(server, remote_client,
1345 remote_client, SILC_NOTIFY_TYPE_KILLED,
1346 3, killed->data, killed->len,
1347 comment, comment ? strlen(comment) : 0,
1348 killer->data, killer->len);
1350 /* Send KILLED notify to primary route */
1351 silc_server_send_notify_killed(server, SILC_PRIMARY_ROUTE(server),
1352 SILC_BROADCAST(server), remote_client->id,
1353 comment, killer_id, killer_id_type);
1355 /* Send KILLED notify to the client directly */
1356 if (remote_client->connection || remote_client->router)
1357 silc_server_send_notify_killed(server, remote_client->connection ?
1358 remote_client->connection :
1359 remote_client->router->connection, FALSE,
1360 remote_client->id, comment,
1361 killer_id, killer_id_type);
1363 /* Remove the client from all channels. This generates new keys to the
1364 channels as well. */
1365 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
1368 /* Remove the client entry, If it is locally connected then we will also
1369 disconnect the client here */
1370 if (remote_client->connection) {
1371 /* Remove locally conneted client */
1372 SilcSocketConnection sock = remote_client->connection;
1373 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
1374 silc_server_close_connection(server, sock);
1376 /* Update statistics */
1377 server->stat.clients--;
1378 if (server->stat.cell_clients)
1379 server->stat.cell_clients--;
1380 SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
1381 SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
1383 if (SILC_IS_LOCAL(remote_client)) {
1384 server->stat.my_clients--;
1385 silc_schedule_task_del_by_context(server->schedule, remote_client);
1386 silc_idlist_del_data(remote_client);
1389 /* Remove remote client */
1390 if (!silc_idlist_del_client(server->global_list, remote_client)) {
1391 /* Remove this client from watcher list if it is */
1392 silc_server_del_from_watcher_list(server, remote_client);
1393 silc_idlist_del_client(server->local_list, remote_client);
1397 silc_buffer_free(killer);
1398 silc_buffer_free(killed);
1403 SilcClientEntry client;
1404 SilcNotifyType notify;
1405 const char *new_nick;
1406 } WatcherNotifyContext;
1409 silc_server_check_watcher_list_foreach(void *key, void *context,
1412 WatcherNotifyContext *notify = user_context;
1413 SilcClientEntry entry = context;
1414 SilcSocketConnection sock;
1416 if (entry == notify->client)
1419 sock = silc_server_get_client_route(notify->server, NULL, 0, entry->id,
1422 SILC_LOG_DEBUG(("Sending WATCH notify to %s",
1423 silc_id_render(entry->id, SILC_ID_CLIENT)));
1425 /* Send the WATCH notify */
1426 silc_server_send_notify_watch(notify->server, sock, entry,
1428 notify->new_nick ? notify->new_nick :
1429 (const char *)notify->client->nickname,
1434 /* This function checks whether the `client' nickname is being watched
1435 by someone, and notifies the watcher of the notify change of notify
1436 type indicated by `notify'. */
1438 bool silc_server_check_watcher_list(SilcServer server,
1439 SilcClientEntry client,
1440 const char *new_nick,
1441 SilcNotifyType notify)
1443 unsigned char hash[16];
1444 WatcherNotifyContext n;
1446 SILC_LOG_DEBUG(("Checking watcher list %s",
1447 client->nickname ? client->nickname : (unsigned char *)""));
1449 /* If the watching is rejected by the client do nothing */
1450 if (client->mode & SILC_UMODE_REJECT_WATCHING)
1453 /* Make hash from the nick, or take it from Client ID */
1454 if (client->nickname) {
1456 memset(nick, 0, sizeof(nick));
1457 silc_to_lower(client->nickname, nick, sizeof(nick) - 1);
1458 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
1460 memset(hash, 0, sizeof(hash));
1461 memcpy(hash, client->id->hash, sizeof(client->id->hash));
1466 n.new_nick = new_nick;
1469 /* Send notify to all watchers */
1470 silc_hash_table_find_foreach(server->watcher_list, hash,
1471 silc_server_check_watcher_list_foreach, &n);
1476 /* Remove the `client' from watcher list. After calling this the `client'
1477 is not watching any nicknames. */
1479 bool silc_server_del_from_watcher_list(SilcServer server,
1480 SilcClientEntry client)
1482 SilcHashTableList htl;
1484 SilcClientEntry entry;
1487 silc_hash_table_list(server->watcher_list, &htl);
1488 while (silc_hash_table_get(&htl, &key, (void **)&entry)) {
1489 if (entry == client) {
1490 silc_hash_table_del_by_context(server->watcher_list, key, client);
1493 SILC_LOG_DEBUG(("Removing %s from WATCH list",
1494 silc_id_render(client->id, SILC_ID_CLIENT)));
1496 /* Now check whether there still exists entries with this key, if not
1497 then free the key to not leak memory. */
1498 if (!silc_hash_table_find(server->watcher_list, key, NULL, NULL))
1504 silc_hash_table_list_reset(&htl);
1509 /* Force the client indicated by `chl' to change the channel user mode
1510 on channel indicated by `channel' to `forced_mode'. */
1512 bool silc_server_force_cumode_change(SilcServer server,
1513 SilcSocketConnection sock,
1514 SilcChannelEntry channel,
1515 SilcChannelClientEntry chl,
1516 SilcUInt32 forced_mode)
1518 SilcBuffer idp1, idp2;
1519 unsigned char cumode[4];
1521 SILC_LOG_DEBUG(("Enforcing sender to change mode"));
1524 silc_server_send_notify_cumode(server, sock, FALSE, channel, forced_mode,
1525 server->id, SILC_ID_SERVER,
1526 chl->client->id, NULL);
1528 idp1 = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1529 idp2 = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
1530 SILC_PUT32_MSB(forced_mode, cumode);
1531 silc_server_send_notify_to_channel(server, sock, channel, FALSE,
1532 SILC_NOTIFY_TYPE_CUMODE_CHANGE,
1533 3, idp1->data, idp1->len,
1534 cumode, sizeof(cumode),
1535 idp2->data, idp2->len);
1536 silc_buffer_free(idp1);
1537 silc_buffer_free(idp2);
1542 /* Find active socket connection by the IP address and port indicated by
1543 `ip' and `port', and socket connection type of `type'. */
1545 SilcSocketConnection
1546 silc_server_find_socket_by_host(SilcServer server,
1547 SilcSocketType type,
1548 const char *ip, SilcUInt16 port)
1552 for (i = 0; i < server->config->param.connections_max; i++) {
1553 if (!server->sockets[i])
1555 if (!strcmp(server->sockets[i]->ip, ip) &&
1556 (!port || server->sockets[i]->port == port) &&
1557 server->sockets[i]->type == type)
1558 return server->sockets[i];