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
467 void silc_server_update_clients_by_server(SilcServer server,
468 SilcServerEntry from,
470 bool resolve_real_server,
473 SilcIDCacheList list = NULL;
474 SilcIDCacheEntry id_cache = NULL;
475 SilcClientEntry client = NULL;
478 SILC_LOG_DEBUG(("Start"));
481 SILC_LOG_DEBUG(("Updating %s", silc_id_render(from->id,
484 SILC_LOG_DEBUG(("to %s", silc_id_render(to->id,
488 if (silc_idcache_get_all(server->global_list->clients, &list)) {
489 if (silc_idcache_list_first(list, &id_cache)) {
491 client = (SilcClientEntry)id_cache->context;
493 /* If entry is disabled skip it. If entry is local to us, do not
494 switch it to anyone else, it is ours so skip it. */
495 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
496 SILC_IS_LOCAL(client)) {
497 if (!silc_idcache_list_next(list, &id_cache))
503 SILC_LOG_DEBUG(("Client (global) %s",
504 silc_id_render(client->id, SILC_ID_CLIENT)));
506 SILC_LOG_DEBUG(("Client->router (global) %s",
507 silc_id_render(client->router->id, SILC_ID_SERVER)));
509 if (client->router == from) {
510 /* Skip clients that are *really* owned by the `from' */
511 if (remove_from && SILC_ID_COMPARE(from->id, client->id,
512 client->id->ip.data_len)) {
513 SILC_LOG_DEBUG(("Found really owned client, skip it"));
514 if (!silc_idcache_list_next(list, &id_cache))
520 if (resolve_real_server) {
522 silc_server_update_clients_by_real_server(server, from, client,
531 if (!silc_idcache_list_next(list, &id_cache))
535 silc_idcache_list_free(list);
539 if (silc_idcache_get_all(server->local_list->clients, &list)) {
540 if (silc_idcache_list_first(list, &id_cache)) {
542 client = (SilcClientEntry)id_cache->context;
544 /* If entry is disabled skip it. If entry is local to us, do not
545 switch it to anyone else, it is ours so skip it. */
546 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
547 SILC_IS_LOCAL(client)) {
548 if (!silc_idcache_list_next(list, &id_cache))
554 SILC_LOG_DEBUG(("Client (local) %s",
555 silc_id_render(client->id, SILC_ID_CLIENT)));
557 SILC_LOG_DEBUG(("Client->router (local) %s",
558 silc_id_render(client->router->id, SILC_ID_SERVER)));
560 if (client->router == from) {
561 /* Skip clients that are *really* owned by the `from' */
562 if (remove_from && SILC_ID_COMPARE(from->id, client->id,
563 client->id->ip.data_len)) {
564 SILC_LOG_DEBUG(("Found really owned client, skip it"));
565 if (!silc_idcache_list_next(list, &id_cache))
571 if (resolve_real_server) {
573 silc_server_update_clients_by_real_server(server, from, client,
576 client->router = from; /* on local list put old from */
582 if (!silc_idcache_list_next(list, &id_cache))
586 silc_idcache_list_free(list);
590 /* Now remove the clients that are still marked as orignated from the
591 `from'. These are the clients that really was owned by the `from' and
592 not just exist behind the `from'. */
593 silc_server_remove_clients_by_server(server, from, TRUE);
596 /* Updates servers that are from `from' to be originated from `to'. This
597 will also update the server's connection to `to's connection. If
598 `local_toggle_enabled' is TRUE then local server's connections are
599 enabled, if FALSE they are disabled. */
601 void silc_server_update_servers_by_server(SilcServer server,
602 SilcServerEntry from,
604 bool local_toggle_enabled)
606 SilcIDCacheList list = NULL;
607 SilcIDCacheEntry id_cache = NULL;
608 SilcServerEntry server_entry = NULL;
610 if (silc_idcache_get_all(server->local_list->servers, &list)) {
611 if (silc_idcache_list_first(list, &id_cache)) {
613 server_entry = (SilcServerEntry)id_cache->context;
615 if (SILC_IS_LOCAL(server_entry)) {
616 if (server_entry != server->id_entry) {
617 if (local_toggle_enabled)
618 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
620 server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
623 /* If entry is local to us, do not switch it to any oneelse,
625 if (!silc_idcache_list_next(list, &id_cache))
631 if (server_entry->router == from) {
632 SILC_LOG_DEBUG(("Updating server (local) %s",
633 server_entry->server_name ?
634 server_entry->server_name : ""));
635 server_entry->router = to;
636 server_entry->connection = to->connection;
639 if (!silc_idcache_list_next(list, &id_cache))
643 silc_idcache_list_free(list);
646 if (silc_idcache_get_all(server->global_list->servers, &list)) {
647 if (silc_idcache_list_first(list, &id_cache)) {
649 server_entry = (SilcServerEntry)id_cache->context;
651 if (SILC_IS_LOCAL(server_entry)) {
652 if (server_entry != server->id_entry) {
653 if (local_toggle_enabled)
654 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
656 server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
659 /* If entry is local to us, do not switch it to anyone else,
661 if (!silc_idcache_list_next(list, &id_cache))
667 if (server_entry->router == from) {
668 SILC_LOG_DEBUG(("Updating server (global) %s",
669 server_entry->server_name ?
670 server_entry->server_name : ""));
671 server_entry->router = to;
672 server_entry->connection = to->connection;
675 if (!silc_idcache_list_next(list, &id_cache))
679 silc_idcache_list_free(list);
683 /* Removes channels that are from `from. */
685 void silc_server_remove_channels_by_server(SilcServer server,
686 SilcServerEntry from)
688 SilcIDCacheList list = NULL;
689 SilcIDCacheEntry id_cache = NULL;
690 SilcChannelEntry channel = NULL;
692 SILC_LOG_DEBUG(("Removing channels by server"));
694 if (silc_idcache_get_all(server->global_list->channels, &list)) {
695 if (silc_idcache_list_first(list, &id_cache)) {
697 channel = (SilcChannelEntry)id_cache->context;
698 if (channel->router == from)
699 silc_idlist_del_channel(server->global_list, channel);
700 if (!silc_idcache_list_next(list, &id_cache))
704 silc_idcache_list_free(list);
708 /* Updates channels that are from `from' to be originated from `to'. */
710 void silc_server_update_channels_by_server(SilcServer server,
711 SilcServerEntry from,
714 SilcIDCacheList list = NULL;
715 SilcIDCacheEntry id_cache = NULL;
716 SilcChannelEntry channel = NULL;
718 SILC_LOG_DEBUG(("Updating channels by server"));
720 if (silc_idcache_get_all(server->global_list->channels, &list)) {
721 if (silc_idcache_list_first(list, &id_cache)) {
723 channel = (SilcChannelEntry)id_cache->context;
724 if (channel->router == from)
725 channel->router = to;
726 if (!silc_idcache_list_next(list, &id_cache))
730 silc_idcache_list_free(list);
734 /* Checks whether given channel has global users. If it does this returns
735 TRUE and FALSE if there is only locally connected clients on the channel. */
737 bool silc_server_channel_has_global(SilcChannelEntry channel)
739 SilcChannelClientEntry chl;
740 SilcHashTableList htl;
742 silc_hash_table_list(channel->user_list, &htl);
743 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
744 if (chl->client->router) {
745 silc_hash_table_list_reset(&htl);
749 silc_hash_table_list_reset(&htl);
754 /* Checks whether given channel has locally connected users. If it does this
755 returns TRUE and FALSE if there is not one locally connected client. */
757 bool silc_server_channel_has_local(SilcChannelEntry channel)
759 SilcChannelClientEntry chl;
760 SilcHashTableList htl;
762 silc_hash_table_list(channel->user_list, &htl);
763 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
764 if (!chl->client->router) {
765 silc_hash_table_list_reset(&htl);
769 silc_hash_table_list_reset(&htl);
774 /* This function removes the channel and all users on the channel, unless
775 the channel is permanent. In this case the channel is disabled but all
776 users are removed from the channel. Returns TRUE if the channel is
777 destroyed totally, and FALSE if it is permanent and remains. */
779 bool silc_server_channel_delete(SilcServer server,
780 SilcChannelEntry channel)
782 SilcChannelClientEntry chl;
783 SilcHashTableList htl;
784 bool delchan = !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH);
787 SILC_LOG_DEBUG(("Deleting %s channel", channel->channel_name));
789 /* Update statistics */
790 if (server->server_type == SILC_ROUTER)
791 server->stat.chanclients -= channel->user_count;
793 /* Totally delete the channel and all users on the channel. The
794 users are deleted automatically in silc_idlist_del_channel. */
795 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
796 if (silc_idlist_del_channel(server->local_list, channel)) {
797 server->stat.my_channels--;
798 if (server->server_type == SILC_ROUTER) {
799 server->stat.channels--;
800 server->stat.cell_channels--;
803 if (silc_idlist_del_channel(server->global_list, channel))
804 if (server->server_type == SILC_ROUTER)
805 server->stat.channels--;
811 /* Channel is permanent, do not remove it, remove only users */
812 channel->disabled = TRUE;
813 silc_hash_table_list(channel->user_list, &htl);
814 while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
815 silc_hash_table_del(chl->client->channels, channel);
816 silc_hash_table_del(channel->user_list, chl->client);
817 channel->user_count--;
819 /* Update statistics */
820 if (SILC_IS_LOCAL(chl->client))
821 server->stat.my_chanclients--;
822 if (server->server_type == SILC_ROUTER) {
823 server->stat.cell_chanclients--;
824 server->stat.chanclients--;
829 silc_hash_table_list_reset(&htl);
831 SILC_LOG_DEBUG(("Channel %s remains", channel->channel_name));
836 /* Returns TRUE if the given client is on the channel. FALSE if not.
837 This works because we assure that the user list on the channel is
838 always in up to date thus we can only check the channel list from
839 `client' which is faster than checking the user list from `channel'. */
841 bool silc_server_client_on_channel(SilcClientEntry client,
842 SilcChannelEntry channel,
843 SilcChannelClientEntry *chl)
845 if (!client || !channel)
848 return silc_hash_table_find(client->channels, channel, NULL,
852 /* Checks string for bad characters and returns TRUE if they are found. */
854 bool silc_server_name_bad_chars(const char *name, SilcUInt32 name_len)
858 for (i = 0; i < name_len; i++) {
859 if (!isascii(name[i]))
861 if (name[i] <= 32) return TRUE;
862 if (name[i] == ' ') return TRUE;
863 if (name[i] == '*') return TRUE;
864 if (name[i] == '?') return TRUE;
865 if (name[i] == ',') return TRUE;
871 /* Modifies the `name' if it includes bad characters and returns new
872 allocated name that does not include bad characters. */
874 char *silc_server_name_modify_bad(const char *name, SilcUInt32 name_len)
877 char *newname = strdup(name);
879 for (i = 0; i < name_len; i++) {
880 if (!isascii(newname[i])) newname[i] = '_';
881 if (newname[i] <= 32) newname[i] = '_';
882 if (newname[i] == ' ') newname[i] = '_';
883 if (newname[i] == '*') newname[i] = '_';
884 if (newname[i] == '?') newname[i] = '_';
885 if (newname[i] == ',') newname[i] = '_';
891 /* Find number of sockets by IP address indicated by `ip'. Returns 0 if
892 socket connections with the IP address does not exist. */
894 SilcUInt32 silc_server_num_sockets_by_ip(SilcServer server, const char *ip,
899 for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
900 if (server->sockets[i] && !strcmp(server->sockets[i]->ip, ip) &&
901 server->sockets[i]->type == type)
908 /* Find number of sockets by IP address indicated by remote host, indicatd
909 by `ip' or `hostname', `port', and `type'. Returns 0 if socket connections
910 does not exist. If `ip' is provided then `hostname' is ignored. */
912 SilcUInt32 silc_server_num_sockets_by_remote(SilcServer server,
914 const char *hostname,
920 if (!ip && !hostname)
923 for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
924 if (server->sockets[i] &&
925 ((ip && !strcmp(server->sockets[i]->ip, ip)) ||
926 (hostname && !strcmp(server->sockets[i]->hostname, hostname))) &&
927 server->sockets[i]->port == port &&
928 server->sockets[i]->type == type)
935 /* Finds locally cached public key by the public key received in the SKE.
936 If we have it locally cached then we trust it and will use it in the
937 authentication protocol. Returns the locally cached public key or NULL
938 if we do not find the public key. */
940 SilcPublicKey silc_server_find_public_key(SilcServer server,
941 SilcHashTable local_public_keys,
942 SilcPublicKey remote_public_key)
944 SilcPublicKey cached_key;
946 SILC_LOG_DEBUG(("Find remote public key (%d keys in local cache)",
947 silc_hash_table_count(local_public_keys)));
949 if (!silc_hash_table_find_ext(local_public_keys, remote_public_key,
950 (void **)&cached_key, NULL,
951 silc_hash_public_key, NULL,
952 silc_hash_public_key_compare, NULL)) {
953 SILC_LOG_ERROR(("Public key not found"));
957 SILC_LOG_DEBUG(("Found public key"));
962 /* This returns the first public key from the table of public keys. This
963 is used only in cases where single public key exists in the table and
964 we want to get a pointer to it. For public key tables that has multiple
965 keys in it the silc_server_find_public_key must be used. */
967 SilcPublicKey silc_server_get_public_key(SilcServer server,
968 SilcHashTable local_public_keys)
970 SilcPublicKey cached_key;
971 SilcHashTableList htl;
973 SILC_LOG_DEBUG(("Start"));
975 assert(silc_hash_table_count(local_public_keys) < 2);
977 silc_hash_table_list(local_public_keys, &htl);
978 if (!silc_hash_table_get(&htl, NULL, (void **)&cached_key))
980 silc_hash_table_list_reset(&htl);
985 /* Check whether the connection `sock' is allowed to connect to us. This
986 checks for example whether there is too much connections for this host,
987 and required version for the host etc. */
989 bool silc_server_connection_allowed(SilcServer server,
990 SilcSocketConnection sock,
992 SilcServerConfigConnParams *global,
993 SilcServerConfigConnParams *params,
996 SilcUInt32 conn_number = (type == SILC_SOCKET_TYPE_CLIENT ?
997 server->stat.my_clients :
998 type == SILC_SOCKET_TYPE_SERVER ?
999 server->stat.my_servers :
1000 server->stat.my_routers);
1001 SilcUInt32 num_sockets, max_hosts, max_per_host;
1002 SilcUInt32 r_protocol_version, l_protocol_version;
1003 SilcUInt32 r_software_version, l_software_version;
1004 char *r_vendor_version = NULL, *l_vendor_version;
1006 SILC_LOG_DEBUG(("Checking whether connection is allowed"));
1010 l_protocol_version =
1011 silc_version_to_num(params && params->version_protocol ?
1012 params->version_protocol :
1013 global->version_protocol);
1014 l_software_version =
1015 silc_version_to_num(params && params->version_software ?
1016 params->version_software :
1017 global->version_software);
1018 l_vendor_version = (params && params->version_software_vendor ?
1019 params->version_software_vendor :
1020 global->version_software_vendor);
1022 if (ske && silc_ske_parse_version(ske, &r_protocol_version, NULL,
1023 &r_software_version, NULL,
1024 &r_vendor_version)) {
1025 sock->version = r_protocol_version;
1027 /* Match protocol version */
1028 if (l_protocol_version && r_protocol_version &&
1029 r_protocol_version < l_protocol_version) {
1030 SILC_LOG_INFO(("Connection %s (%s) is too old version",
1031 sock->hostname, sock->ip));
1032 silc_server_disconnect_remote(server, sock,
1033 SILC_STATUS_ERR_BAD_VERSION,
1034 "You support too old protocol version");
1038 /* Math software version */
1039 if (l_software_version && r_software_version &&
1040 r_software_version < l_software_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 software version");
1049 /* Regex match vendor version */
1050 if (l_vendor_version && r_vendor_version &&
1051 !silc_string_match(l_vendor_version, r_vendor_version)) {
1052 SILC_LOG_INFO(("Connection %s (%s) is unsupported version",
1053 sock->hostname, sock->ip));
1054 silc_server_disconnect_remote(server, sock,
1055 SILC_STATUS_ERR_BAD_VERSION,
1056 "Your software is not supported");
1060 silc_free(r_vendor_version);
1062 /* Check for maximum connections limit */
1064 num_sockets = silc_server_num_sockets_by_ip(server, sock->ip, type);
1065 max_hosts = (params ? params->connections_max : global->connections_max);
1066 max_per_host = (params ? params->connections_max_per_host :
1067 global->connections_max_per_host);
1069 if (max_hosts && conn_number >= max_hosts) {
1070 SILC_LOG_INFO(("Server is full, closing %s (%s) connection",
1071 sock->hostname, sock->ip));
1072 silc_server_disconnect_remote(server, sock,
1073 SILC_STATUS_ERR_RESOURCE_LIMIT,
1074 "Server is full, try again later");
1078 if (num_sockets >= max_per_host) {
1079 SILC_LOG_INFO(("Too many connections from %s (%s), closing connection",
1080 sock->hostname, sock->ip));
1081 silc_server_disconnect_remote(server, sock,
1082 SILC_STATUS_ERR_RESOURCE_LIMIT,
1083 "Too many connections from your host");
1090 /* Checks that client has rights to add or remove channel modes. If any
1091 of the checks fails FALSE is returned. */
1093 bool silc_server_check_cmode_rights(SilcServer server,
1094 SilcChannelEntry channel,
1095 SilcChannelClientEntry client,
1098 bool is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1099 bool is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1101 /* Check whether has rights to change anything */
1102 if (!is_op && !is_fo)
1105 /* Check whether has rights to change everything */
1109 /* Founder implies operator */
1113 /* We know that client is channel operator, check that they are not
1114 changing anything that requires channel founder rights. Rest of the
1115 modes are available automatically for channel operator. */
1117 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1118 if (is_op && !is_fo)
1121 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1122 if (is_op && !is_fo)
1127 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1128 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
1129 if (is_op && !is_fo)
1133 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1134 if (is_op && !is_fo)
1139 if (mode & SILC_CHANNEL_MODE_CIPHER) {
1140 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
1141 if (is_op && !is_fo)
1145 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1146 if (is_op && !is_fo)
1151 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1152 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
1153 if (is_op && !is_fo)
1157 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1158 if (is_op && !is_fo)
1163 if (mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1164 if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS)) {
1165 if (is_op && !is_fo)
1169 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1170 if (is_op && !is_fo)
1175 if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1176 if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS)) {
1177 if (is_op && !is_fo)
1181 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1182 if (is_op && !is_fo)
1190 /* Check that the client has rights to change its user mode. Returns
1191 FALSE if setting some mode is not allowed. */
1193 bool silc_server_check_umode_rights(SilcServer server,
1194 SilcClientEntry client,
1197 bool server_op = FALSE, router_op = FALSE;
1199 if (mode & SILC_UMODE_SERVER_OPERATOR) {
1200 /* Cannot set server operator mode (must use OPER command) */
1201 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR))
1204 /* Remove the server operator rights */
1205 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
1209 if (mode & SILC_UMODE_ROUTER_OPERATOR) {
1210 /* Cannot set router operator mode (must use SILCOPER command) */
1211 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR))
1214 /* Remove the router operator rights */
1215 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
1220 SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR);
1222 SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR);
1227 /* This function is used to send the notify packets and motd to the
1228 incoming client connection. */
1230 void silc_server_send_connect_notifys(SilcServer server,
1231 SilcSocketConnection sock,
1232 SilcClientEntry client)
1234 SilcIDListData idata = (SilcIDListData)client;
1236 SILC_LOG_DEBUG(("Send welcome notifys"));
1238 /* Send some nice info to the client */
1239 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1240 ("Welcome to the SILC Network %s",
1242 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1243 ("Your host is %s, running version %s",
1244 server->server_name, server_version));
1246 if (server->server_type == SILC_ROUTER) {
1247 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1248 ("There are %d clients, %d servers and %d "
1249 "routers in SILC Network",
1250 server->stat.clients, server->stat.servers + 1,
1251 server->stat.routers));
1253 if (server->stat.clients && server->stat.servers + 1)
1254 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1255 ("There are %d clients, %d servers and %d "
1256 "routers in SILC Network",
1257 server->stat.clients, server->stat.servers + 1,
1258 (server->standalone ? 0 :
1259 !server->stat.routers ? 1 :
1260 server->stat.routers)));
1263 if (server->stat.cell_clients && server->stat.cell_servers + 1)
1264 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1265 ("There are %d clients on %d server in our cell",
1266 server->stat.cell_clients,
1267 server->stat.cell_servers + 1));
1268 if (server->server_type == SILC_ROUTER) {
1269 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1270 ("I have %d clients, %d channels, %d servers and "
1272 server->stat.my_clients,
1273 server->stat.my_channels,
1274 server->stat.my_servers,
1275 server->stat.my_routers));
1277 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1278 ("I have %d clients and %d channels formed",
1279 server->stat.my_clients,
1280 server->stat.my_channels));
1283 if (server->stat.server_ops || server->stat.router_ops)
1284 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1285 ("There are %d server operators and %d router "
1287 server->stat.server_ops,
1288 server->stat.router_ops));
1289 if (server->stat.my_router_ops + server->stat.my_server_ops)
1290 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1291 ("I have %d operators online",
1292 server->stat.my_router_ops +
1293 server->stat.my_server_ops));
1295 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1296 ("Your connection is secured with %s cipher, "
1297 "key length %d bits",
1298 idata->send_key->cipher->name,
1299 idata->send_key->cipher->key_len));
1300 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1301 ("Your current nickname is %s",
1305 silc_server_send_motd(server, sock);
1308 /* Kill the client indicated by `remote_client' sending KILLED notify
1309 to the client, to all channels client has joined and to primary
1310 router if needed. The killed client is also removed from all channels. */
1312 void silc_server_kill_client(SilcServer server,
1313 SilcClientEntry remote_client,
1314 const char *comment,
1316 SilcIdType killer_id_type)
1318 SilcBuffer killed, killer;
1320 SILC_LOG_DEBUG(("Killing client %s",
1321 silc_id_render(remote_client->id, SILC_ID_CLIENT)));
1323 /* Send the KILL notify packets. First send it to the channel, then
1324 to our primary router and then directly to the client who is being
1325 killed right now. */
1327 killed = silc_id_payload_encode(remote_client->id, SILC_ID_CLIENT);
1328 killer = silc_id_payload_encode(killer_id, killer_id_type);
1330 /* Send KILLED notify to the channels. It is not sent to the client
1331 as it will be sent differently destined directly to the client and not
1333 silc_server_send_notify_on_channels(server, remote_client,
1334 remote_client, SILC_NOTIFY_TYPE_KILLED,
1335 3, killed->data, killed->len,
1336 comment, comment ? strlen(comment) : 0,
1337 killer->data, killer->len);
1339 /* Send KILLED notify to primary route */
1340 silc_server_send_notify_killed(server, SILC_PRIMARY_ROUTE(server),
1341 SILC_BROADCAST(server), remote_client->id,
1342 comment, killer_id, killer_id_type);
1344 /* Send KILLED notify to the client directly */
1345 if (remote_client->connection || remote_client->router)
1346 silc_server_send_notify_killed(server, remote_client->connection ?
1347 remote_client->connection :
1348 remote_client->router->connection, FALSE,
1349 remote_client->id, comment,
1350 killer_id, killer_id_type);
1352 /* Remove the client from all channels. This generates new keys to the
1353 channels as well. */
1354 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
1357 /* Remove the client entry, If it is locally connected then we will also
1358 disconnect the client here */
1359 if (remote_client->connection) {
1360 /* Remove locally conneted client */
1361 SilcSocketConnection sock = remote_client->connection;
1362 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
1363 silc_server_close_connection(server, sock);
1365 /* Update statistics */
1366 server->stat.clients--;
1367 if (server->stat.cell_clients)
1368 server->stat.cell_clients--;
1369 SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
1370 SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
1372 if (SILC_IS_LOCAL(remote_client)) {
1373 server->stat.my_clients--;
1374 silc_schedule_task_del_by_context(server->schedule, remote_client);
1375 silc_idlist_del_data(remote_client);
1378 /* Remove remote client */
1379 if (!silc_idlist_del_client(server->global_list, remote_client)) {
1380 /* Remove this client from watcher list if it is */
1381 silc_server_del_from_watcher_list(server, remote_client);
1382 silc_idlist_del_client(server->local_list, remote_client);
1386 silc_buffer_free(killer);
1387 silc_buffer_free(killed);
1392 SilcClientEntry client;
1393 SilcNotifyType notify;
1394 const char *new_nick;
1395 } WatcherNotifyContext;
1398 silc_server_check_watcher_list_foreach(void *key, void *context,
1401 WatcherNotifyContext *notify = user_context;
1402 SilcClientEntry entry = context;
1403 SilcSocketConnection sock;
1405 if (entry == notify->client)
1408 sock = silc_server_get_client_route(notify->server, NULL, 0, entry->id,
1411 SILC_LOG_DEBUG(("Sending WATCH notify to %s",
1412 silc_id_render(entry->id, SILC_ID_CLIENT)));
1414 /* Send the WATCH notify */
1415 silc_server_send_notify_watch(notify->server, sock, entry,
1417 notify->new_nick ? notify->new_nick :
1418 (const char *)notify->client->nickname,
1423 /* This function checks whether the `client' nickname is being watched
1424 by someone, and notifies the watcher of the notify change of notify
1425 type indicated by `notify'. */
1427 bool silc_server_check_watcher_list(SilcServer server,
1428 SilcClientEntry client,
1429 const char *new_nick,
1430 SilcNotifyType notify)
1432 unsigned char hash[16];
1433 WatcherNotifyContext n;
1435 SILC_LOG_DEBUG(("Checking watcher list %s",
1436 client->nickname ? client->nickname : (unsigned char *)""));
1438 /* If the watching is rejected by the client do nothing */
1439 if (client->mode & SILC_UMODE_REJECT_WATCHING)
1442 /* Make hash from the nick, or take it from Client ID */
1443 if (client->nickname) {
1445 memset(nick, 0, sizeof(nick));
1446 silc_to_lower(client->nickname, nick, sizeof(nick) - 1);
1447 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
1449 memset(hash, 0, sizeof(hash));
1450 memcpy(hash, client->id->hash, sizeof(client->id->hash));
1455 n.new_nick = new_nick;
1458 /* Send notify to all watchers */
1459 silc_hash_table_find_foreach(server->watcher_list, hash,
1460 silc_server_check_watcher_list_foreach, &n);
1465 /* Remove the `client' from watcher list. After calling this the `client'
1466 is not watching any nicknames. */
1468 bool silc_server_del_from_watcher_list(SilcServer server,
1469 SilcClientEntry client)
1471 SilcHashTableList htl;
1473 SilcClientEntry entry;
1476 silc_hash_table_list(server->watcher_list, &htl);
1477 while (silc_hash_table_get(&htl, &key, (void **)&entry)) {
1478 if (entry == client) {
1479 silc_hash_table_del_by_context(server->watcher_list, key, client);
1482 SILC_LOG_DEBUG(("Removing %s from WATCH list",
1483 silc_id_render(client->id, SILC_ID_CLIENT)));
1485 /* Now check whether there still exists entries with this key, if not
1486 then free the key to not leak memory. */
1487 if (!silc_hash_table_find(server->watcher_list, key, NULL, NULL))
1493 silc_hash_table_list_reset(&htl);
1498 /* Force the client indicated by `chl' to change the channel user mode
1499 on channel indicated by `channel' to `forced_mode'. */
1501 bool silc_server_force_cumode_change(SilcServer server,
1502 SilcSocketConnection sock,
1503 SilcChannelEntry channel,
1504 SilcChannelClientEntry chl,
1505 SilcUInt32 forced_mode)
1507 SilcBuffer idp1, idp2;
1508 unsigned char cumode[4];
1510 SILC_LOG_DEBUG(("Enforcing sender to change mode"));
1513 silc_server_send_notify_cumode(server, sock, FALSE, channel, forced_mode,
1514 server->id, SILC_ID_SERVER,
1515 chl->client->id, NULL);
1517 idp1 = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1518 idp2 = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
1519 SILC_PUT32_MSB(forced_mode, cumode);
1520 silc_server_send_notify_to_channel(server, sock, channel, FALSE,
1521 SILC_NOTIFY_TYPE_CUMODE_CHANGE,
1522 3, idp1->data, idp1->len,
1523 cumode, sizeof(cumode),
1524 idp2->data, idp2->len);
1525 silc_buffer_free(idp1);
1526 silc_buffer_free(idp2);