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;
480 SILC_LOG_DEBUG(("Updating %s", silc_id_render(from->id,
483 SILC_LOG_DEBUG(("to %s", silc_id_render(to->id,
487 if (silc_idcache_get_all(server->global_list->clients, &list)) {
488 if (silc_idcache_list_first(list, &id_cache)) {
490 client = (SilcClientEntry)id_cache->context;
492 /* If entry is disabled skip it. If entry is local to us, do not
493 switch it to anyone else, it is ours so skip it. */
494 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
495 SILC_IS_LOCAL(client)) {
496 if (!silc_idcache_list_next(list, &id_cache))
502 SILC_LOG_DEBUG(("Client (global) %s",
503 silc_id_render(client->id, SILC_ID_CLIENT)));
505 SILC_LOG_DEBUG(("Client->router (global) %s",
506 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 /* All are changed */
535 if (!silc_idcache_list_next(list, &id_cache))
539 silc_idcache_list_free(list);
543 if (silc_idcache_get_all(server->local_list->clients, &list)) {
544 if (silc_idcache_list_first(list, &id_cache)) {
546 client = (SilcClientEntry)id_cache->context;
548 /* If entry is disabled skip it. If entry is local to us, do not
549 switch it to anyone else, it is ours so skip it. */
550 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
551 SILC_IS_LOCAL(client)) {
552 if (!silc_idcache_list_next(list, &id_cache))
558 SILC_LOG_DEBUG(("Client (local) %s",
559 silc_id_render(client->id, SILC_ID_CLIENT)));
561 SILC_LOG_DEBUG(("Client->router (local) %s",
562 silc_id_render(client->router->id, SILC_ID_SERVER)));
565 if (client->router == from) {
566 /* Skip clients that are *really* owned by the `from' */
567 if (remove_from && SILC_ID_COMPARE(from->id, client->id,
568 client->id->ip.data_len)) {
569 SILC_LOG_DEBUG(("Found really owned client, skip it"));
570 if (!silc_idcache_list_next(list, &id_cache))
576 if (resolve_real_server) {
578 silc_server_update_clients_by_real_server(server, from, client,
581 client->router = from; /* on local list put old from */
587 /* All are changed */
591 if (!silc_idcache_list_next(list, &id_cache))
595 silc_idcache_list_free(list);
599 /* Now remove the clients that are still marked as orignated from the
600 `from'. These are the clients that really was owned by the `from' and
601 not just exist behind the `from'. */
602 silc_server_remove_clients_by_server(server, from, TRUE);
605 /* Updates servers that are from `from' to be originated from `to'. This
606 will also update the server's connection to `to's connection. If
607 `local_toggle_enabled' is TRUE then local server's connections are
608 enabled, if FALSE they are disabled. */
610 void silc_server_update_servers_by_server(SilcServer server,
611 SilcServerEntry from,
613 bool local_toggle_enabled)
615 SilcIDCacheList list = NULL;
616 SilcIDCacheEntry id_cache = NULL;
617 SilcServerEntry server_entry = NULL;
619 if (silc_idcache_get_all(server->local_list->servers, &list)) {
620 if (silc_idcache_list_first(list, &id_cache)) {
622 server_entry = (SilcServerEntry)id_cache->context;
624 if (SILC_IS_LOCAL(server_entry)) {
625 if (server_entry != server->id_entry) {
626 if (local_toggle_enabled)
627 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
629 server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
632 /* If entry is local to us, do not switch it to any oneelse,
634 if (!silc_idcache_list_next(list, &id_cache))
640 if (server_entry->router == from) {
641 SILC_LOG_DEBUG(("Updating server (local) %s",
642 server_entry->server_name ?
643 server_entry->server_name : ""));
644 server_entry->router = to;
645 server_entry->connection = to->connection;
648 if (!silc_idcache_list_next(list, &id_cache))
652 silc_idcache_list_free(list);
655 if (silc_idcache_get_all(server->global_list->servers, &list)) {
656 if (silc_idcache_list_first(list, &id_cache)) {
658 server_entry = (SilcServerEntry)id_cache->context;
660 if (SILC_IS_LOCAL(server_entry)) {
661 if (server_entry != server->id_entry) {
662 if (local_toggle_enabled)
663 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
665 server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
668 /* If entry is local to us, do not switch it to anyone else,
670 if (!silc_idcache_list_next(list, &id_cache))
676 if (server_entry->router == from) {
677 SILC_LOG_DEBUG(("Updating server (global) %s",
678 server_entry->server_name ?
679 server_entry->server_name : ""));
680 server_entry->router = to;
681 server_entry->connection = to->connection;
684 if (!silc_idcache_list_next(list, &id_cache))
688 silc_idcache_list_free(list);
692 /* Removes channels that are from `from. */
694 void silc_server_remove_channels_by_server(SilcServer server,
695 SilcServerEntry from)
697 SilcIDCacheList list = NULL;
698 SilcIDCacheEntry id_cache = NULL;
699 SilcChannelEntry channel = NULL;
701 SILC_LOG_DEBUG(("Removing channels by server"));
703 if (silc_idcache_get_all(server->global_list->channels, &list)) {
704 if (silc_idcache_list_first(list, &id_cache)) {
706 channel = (SilcChannelEntry)id_cache->context;
707 if (channel->router == from)
708 silc_idlist_del_channel(server->global_list, channel);
709 if (!silc_idcache_list_next(list, &id_cache))
713 silc_idcache_list_free(list);
717 /* Updates channels that are from `from' to be originated from `to'. */
719 void silc_server_update_channels_by_server(SilcServer server,
720 SilcServerEntry from,
723 SilcIDCacheList list = NULL;
724 SilcIDCacheEntry id_cache = NULL;
725 SilcChannelEntry channel = NULL;
727 SILC_LOG_DEBUG(("Updating channels by server"));
729 if (silc_idcache_get_all(server->global_list->channels, &list)) {
730 if (silc_idcache_list_first(list, &id_cache)) {
732 channel = (SilcChannelEntry)id_cache->context;
733 if (channel->router == from)
734 channel->router = to;
735 if (!silc_idcache_list_next(list, &id_cache))
739 silc_idcache_list_free(list);
743 /* Checks whether given channel has global users. If it does this returns
744 TRUE and FALSE if there is only locally connected clients on the channel. */
746 bool silc_server_channel_has_global(SilcChannelEntry channel)
748 SilcChannelClientEntry chl;
749 SilcHashTableList htl;
751 silc_hash_table_list(channel->user_list, &htl);
752 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
753 if (chl->client->router) {
754 silc_hash_table_list_reset(&htl);
758 silc_hash_table_list_reset(&htl);
763 /* Checks whether given channel has locally connected users. If it does this
764 returns TRUE and FALSE if there is not one locally connected client. */
766 bool silc_server_channel_has_local(SilcChannelEntry channel)
768 SilcChannelClientEntry chl;
769 SilcHashTableList htl;
771 silc_hash_table_list(channel->user_list, &htl);
772 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
773 if (!chl->client->router) {
774 silc_hash_table_list_reset(&htl);
778 silc_hash_table_list_reset(&htl);
783 /* This function removes the channel and all users on the channel, unless
784 the channel is permanent. In this case the channel is disabled but all
785 users are removed from the channel. Returns TRUE if the channel is
786 destroyed totally, and FALSE if it is permanent and remains. */
788 bool silc_server_channel_delete(SilcServer server,
789 SilcChannelEntry channel)
791 SilcChannelClientEntry chl;
792 SilcHashTableList htl;
793 bool delchan = !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH);
796 SILC_LOG_DEBUG(("Deleting %s channel", channel->channel_name));
798 /* Update statistics */
799 if (server->server_type == SILC_ROUTER)
800 server->stat.chanclients -= channel->user_count;
802 /* Totally delete the channel and all users on the channel. The
803 users are deleted automatically in silc_idlist_del_channel. */
804 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
805 if (silc_idlist_del_channel(server->local_list, channel)) {
806 server->stat.my_channels--;
807 if (server->server_type == SILC_ROUTER) {
808 server->stat.channels--;
809 server->stat.cell_channels--;
812 if (silc_idlist_del_channel(server->global_list, channel))
813 if (server->server_type == SILC_ROUTER)
814 server->stat.channels--;
820 /* Channel is permanent, do not remove it, remove only users */
821 channel->disabled = TRUE;
822 silc_hash_table_list(channel->user_list, &htl);
823 while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
824 silc_hash_table_del(chl->client->channels, channel);
825 silc_hash_table_del(channel->user_list, chl->client);
826 channel->user_count--;
828 /* Update statistics */
829 if (SILC_IS_LOCAL(chl->client))
830 server->stat.my_chanclients--;
831 if (server->server_type == SILC_ROUTER) {
832 server->stat.cell_chanclients--;
833 server->stat.chanclients--;
838 silc_hash_table_list_reset(&htl);
840 SILC_LOG_DEBUG(("Channel %s remains", channel->channel_name));
845 /* Returns TRUE if the given client is on the channel. FALSE if not.
846 This works because we assure that the user list on the channel is
847 always in up to date thus we can only check the channel list from
848 `client' which is faster than checking the user list from `channel'. */
850 bool silc_server_client_on_channel(SilcClientEntry client,
851 SilcChannelEntry channel,
852 SilcChannelClientEntry *chl)
854 if (!client || !channel)
857 return silc_hash_table_find(client->channels, channel, NULL,
861 /* Checks string for bad characters and returns TRUE if they are found. */
863 bool silc_server_name_bad_chars(const char *name, SilcUInt32 name_len)
867 for (i = 0; i < name_len; i++) {
868 if (!isascii(name[i]))
870 if (name[i] <= 32) return TRUE;
871 if (name[i] == ' ') return TRUE;
872 if (name[i] == '*') return TRUE;
873 if (name[i] == '?') return TRUE;
874 if (name[i] == ',') return TRUE;
880 /* Modifies the `name' if it includes bad characters and returns new
881 allocated name that does not include bad characters. */
883 char *silc_server_name_modify_bad(const char *name, SilcUInt32 name_len)
886 char *newname = strdup(name);
888 for (i = 0; i < name_len; i++) {
889 if (!isascii(newname[i])) newname[i] = '_';
890 if (newname[i] <= 32) newname[i] = '_';
891 if (newname[i] == ' ') newname[i] = '_';
892 if (newname[i] == '*') newname[i] = '_';
893 if (newname[i] == '?') newname[i] = '_';
894 if (newname[i] == ',') newname[i] = '_';
900 /* Find number of sockets by IP address indicated by `ip'. Returns 0 if
901 socket connections with the IP address does not exist. */
903 SilcUInt32 silc_server_num_sockets_by_ip(SilcServer server, const char *ip,
908 for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
909 if (server->sockets[i] && !strcmp(server->sockets[i]->ip, ip) &&
910 server->sockets[i]->type == type)
917 /* Find number of sockets by IP address indicated by remote host, indicatd
918 by `ip' or `hostname', `port', and `type'. Returns 0 if socket connections
919 does not exist. If `ip' is provided then `hostname' is ignored. */
921 SilcUInt32 silc_server_num_sockets_by_remote(SilcServer server,
923 const char *hostname,
929 if (!ip && !hostname)
932 for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
933 if (server->sockets[i] &&
934 ((ip && !strcmp(server->sockets[i]->ip, ip)) ||
935 (hostname && !strcmp(server->sockets[i]->hostname, hostname))) &&
936 server->sockets[i]->port == port &&
937 server->sockets[i]->type == type)
944 /* Finds locally cached public key by the public key received in the SKE.
945 If we have it locally cached then we trust it and will use it in the
946 authentication protocol. Returns the locally cached public key or NULL
947 if we do not find the public key. */
949 SilcPublicKey silc_server_find_public_key(SilcServer server,
950 SilcHashTable local_public_keys,
951 SilcPublicKey remote_public_key)
953 SilcPublicKey cached_key;
955 SILC_LOG_DEBUG(("Find remote public key (%d keys in local cache)",
956 silc_hash_table_count(local_public_keys)));
958 if (!silc_hash_table_find_ext(local_public_keys, remote_public_key,
959 (void **)&cached_key, NULL,
960 silc_hash_public_key, NULL,
961 silc_hash_public_key_compare, NULL)) {
962 SILC_LOG_ERROR(("Public key not found"));
966 SILC_LOG_DEBUG(("Found public key"));
971 /* This returns the first public key from the table of public keys. This
972 is used only in cases where single public key exists in the table and
973 we want to get a pointer to it. For public key tables that has multiple
974 keys in it the silc_server_find_public_key must be used. */
976 SilcPublicKey silc_server_get_public_key(SilcServer server,
977 SilcHashTable local_public_keys)
979 SilcPublicKey cached_key;
980 SilcHashTableList htl;
982 SILC_LOG_DEBUG(("Start"));
984 assert(silc_hash_table_count(local_public_keys) < 2);
986 silc_hash_table_list(local_public_keys, &htl);
987 if (!silc_hash_table_get(&htl, NULL, (void **)&cached_key))
989 silc_hash_table_list_reset(&htl);
994 /* Check whether the connection `sock' is allowed to connect to us. This
995 checks for example whether there is too much connections for this host,
996 and required version for the host etc. */
998 bool silc_server_connection_allowed(SilcServer server,
999 SilcSocketConnection sock,
1000 SilcSocketType type,
1001 SilcServerConfigConnParams *global,
1002 SilcServerConfigConnParams *params,
1005 SilcUInt32 conn_number = (type == SILC_SOCKET_TYPE_CLIENT ?
1006 server->stat.my_clients :
1007 type == SILC_SOCKET_TYPE_SERVER ?
1008 server->stat.my_servers :
1009 server->stat.my_routers);
1010 SilcUInt32 num_sockets, max_hosts, max_per_host;
1011 SilcUInt32 r_protocol_version, l_protocol_version;
1012 SilcUInt32 r_software_version, l_software_version;
1013 char *r_vendor_version = NULL, *l_vendor_version;
1015 SILC_LOG_DEBUG(("Checking whether connection is allowed"));
1019 l_protocol_version =
1020 silc_version_to_num(params && params->version_protocol ?
1021 params->version_protocol :
1022 global->version_protocol);
1023 l_software_version =
1024 silc_version_to_num(params && params->version_software ?
1025 params->version_software :
1026 global->version_software);
1027 l_vendor_version = (params && params->version_software_vendor ?
1028 params->version_software_vendor :
1029 global->version_software_vendor);
1031 if (ske && silc_ske_parse_version(ske, &r_protocol_version, NULL,
1032 &r_software_version, NULL,
1033 &r_vendor_version)) {
1034 sock->version = r_protocol_version;
1036 /* Match protocol version */
1037 if (l_protocol_version && r_protocol_version &&
1038 r_protocol_version < l_protocol_version) {
1039 SILC_LOG_INFO(("Connection %s (%s) is too old version",
1040 sock->hostname, sock->ip));
1041 silc_server_disconnect_remote(server, sock,
1042 SILC_STATUS_ERR_BAD_VERSION,
1043 "You support too old protocol version");
1047 /* Math software version */
1048 if (l_software_version && r_software_version &&
1049 r_software_version < l_software_version) {
1050 SILC_LOG_INFO(("Connection %s (%s) is too old version",
1051 sock->hostname, sock->ip));
1052 silc_server_disconnect_remote(server, sock,
1053 SILC_STATUS_ERR_BAD_VERSION,
1054 "You support too old software version");
1058 /* Regex match vendor version */
1059 if (l_vendor_version && r_vendor_version &&
1060 !silc_string_match(l_vendor_version, r_vendor_version)) {
1061 SILC_LOG_INFO(("Connection %s (%s) is unsupported version",
1062 sock->hostname, sock->ip));
1063 silc_server_disconnect_remote(server, sock,
1064 SILC_STATUS_ERR_BAD_VERSION,
1065 "Your software is not supported");
1069 silc_free(r_vendor_version);
1071 /* Check for maximum connections limit */
1073 num_sockets = silc_server_num_sockets_by_ip(server, sock->ip, type);
1074 max_hosts = (params ? params->connections_max : global->connections_max);
1075 max_per_host = (params ? params->connections_max_per_host :
1076 global->connections_max_per_host);
1078 if (max_hosts && conn_number >= max_hosts) {
1079 SILC_LOG_INFO(("Server is full, closing %s (%s) connection",
1080 sock->hostname, sock->ip));
1081 silc_server_disconnect_remote(server, sock,
1082 SILC_STATUS_ERR_RESOURCE_LIMIT,
1083 "Server is full, try again later");
1087 if (num_sockets >= max_per_host) {
1088 SILC_LOG_INFO(("Too many connections from %s (%s), closing connection",
1089 sock->hostname, sock->ip));
1090 silc_server_disconnect_remote(server, sock,
1091 SILC_STATUS_ERR_RESOURCE_LIMIT,
1092 "Too many connections from your host");
1099 /* Checks that client has rights to add or remove channel modes. If any
1100 of the checks fails FALSE is returned. */
1102 bool silc_server_check_cmode_rights(SilcServer server,
1103 SilcChannelEntry channel,
1104 SilcChannelClientEntry client,
1107 bool is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1108 bool is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1110 /* Check whether has rights to change anything */
1111 if (!is_op && !is_fo)
1114 /* Check whether has rights to change everything */
1118 /* Founder implies operator */
1122 /* We know that client is channel operator, check that they are not
1123 changing anything that requires channel founder rights. Rest of the
1124 modes are available automatically for channel operator. */
1126 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1127 if (is_op && !is_fo)
1130 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1131 if (is_op && !is_fo)
1136 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1137 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
1138 if (is_op && !is_fo)
1142 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1143 if (is_op && !is_fo)
1148 if (mode & SILC_CHANNEL_MODE_CIPHER) {
1149 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
1150 if (is_op && !is_fo)
1154 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1155 if (is_op && !is_fo)
1160 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1161 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
1162 if (is_op && !is_fo)
1166 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1167 if (is_op && !is_fo)
1172 if (mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1173 if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS)) {
1174 if (is_op && !is_fo)
1178 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1179 if (is_op && !is_fo)
1184 if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1185 if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS)) {
1186 if (is_op && !is_fo)
1190 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1191 if (is_op && !is_fo)
1199 /* Check that the client has rights to change its user mode. Returns
1200 FALSE if setting some mode is not allowed. */
1202 bool silc_server_check_umode_rights(SilcServer server,
1203 SilcClientEntry client,
1206 bool server_op = FALSE, router_op = FALSE;
1208 if (mode & SILC_UMODE_SERVER_OPERATOR) {
1209 /* Cannot set server operator mode (must use OPER command) */
1210 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR))
1213 /* Remove the server operator rights */
1214 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
1218 if (mode & SILC_UMODE_ROUTER_OPERATOR) {
1219 /* Cannot set router operator mode (must use SILCOPER command) */
1220 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR))
1223 /* Remove the router operator rights */
1224 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
1229 SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR);
1231 SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR);
1236 /* This function is used to send the notify packets and motd to the
1237 incoming client connection. */
1239 void silc_server_send_connect_notifys(SilcServer server,
1240 SilcSocketConnection sock,
1241 SilcClientEntry client)
1243 SilcIDListData idata = (SilcIDListData)client;
1245 SILC_LOG_DEBUG(("Send welcome notifys"));
1247 /* Send some nice info to the client */
1248 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1249 ("Welcome to the SILC Network %s",
1251 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1252 ("Your host is %s, running version %s",
1253 server->server_name, server_version));
1255 if (server->server_type == SILC_ROUTER) {
1256 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1257 ("There are %d clients, %d servers and %d "
1258 "routers in SILC Network",
1259 server->stat.clients, server->stat.servers + 1,
1260 server->stat.routers));
1262 if (server->stat.clients && server->stat.servers + 1)
1263 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1264 ("There are %d clients, %d servers and %d "
1265 "routers in SILC Network",
1266 server->stat.clients, server->stat.servers + 1,
1267 (server->standalone ? 0 :
1268 !server->stat.routers ? 1 :
1269 server->stat.routers)));
1272 if (server->stat.cell_clients && server->stat.cell_servers + 1)
1273 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1274 ("There are %d clients on %d server in our cell",
1275 server->stat.cell_clients,
1276 server->stat.cell_servers + 1));
1277 if (server->server_type == SILC_ROUTER) {
1278 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1279 ("I have %d clients, %d channels, %d servers and "
1281 server->stat.my_clients,
1282 server->stat.my_channels,
1283 server->stat.my_servers,
1284 server->stat.my_routers));
1286 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1287 ("I have %d clients and %d channels formed",
1288 server->stat.my_clients,
1289 server->stat.my_channels));
1292 if (server->stat.server_ops || server->stat.router_ops)
1293 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1294 ("There are %d server operators and %d router "
1296 server->stat.server_ops,
1297 server->stat.router_ops));
1298 if (server->stat.my_router_ops + server->stat.my_server_ops)
1299 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1300 ("I have %d operators online",
1301 server->stat.my_router_ops +
1302 server->stat.my_server_ops));
1304 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1305 ("Your connection is secured with %s cipher, "
1306 "key length %d bits",
1307 idata->send_key->cipher->name,
1308 idata->send_key->cipher->key_len));
1309 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1310 ("Your current nickname is %s",
1314 silc_server_send_motd(server, sock);
1317 /* Kill the client indicated by `remote_client' sending KILLED notify
1318 to the client, to all channels client has joined and to primary
1319 router if needed. The killed client is also removed from all channels. */
1321 void silc_server_kill_client(SilcServer server,
1322 SilcClientEntry remote_client,
1323 const char *comment,
1325 SilcIdType killer_id_type)
1327 SilcBuffer killed, killer;
1329 SILC_LOG_DEBUG(("Killing client %s",
1330 silc_id_render(remote_client->id, SILC_ID_CLIENT)));
1332 /* Send the KILL notify packets. First send it to the channel, then
1333 to our primary router and then directly to the client who is being
1334 killed right now. */
1336 killed = silc_id_payload_encode(remote_client->id, SILC_ID_CLIENT);
1337 killer = silc_id_payload_encode(killer_id, killer_id_type);
1339 /* Send KILLED notify to the channels. It is not sent to the client
1340 as it will be sent differently destined directly to the client and not
1342 silc_server_send_notify_on_channels(server, remote_client,
1343 remote_client, SILC_NOTIFY_TYPE_KILLED,
1344 3, killed->data, killed->len,
1345 comment, comment ? strlen(comment) : 0,
1346 killer->data, killer->len);
1348 /* Send KILLED notify to primary route */
1349 silc_server_send_notify_killed(server, SILC_PRIMARY_ROUTE(server),
1350 SILC_BROADCAST(server), remote_client->id,
1351 comment, killer_id, killer_id_type);
1353 /* Send KILLED notify to the client directly */
1354 if (remote_client->connection || remote_client->router)
1355 silc_server_send_notify_killed(server, remote_client->connection ?
1356 remote_client->connection :
1357 remote_client->router->connection, FALSE,
1358 remote_client->id, comment,
1359 killer_id, killer_id_type);
1361 /* Remove the client from all channels. This generates new keys to the
1362 channels as well. */
1363 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
1366 /* Remove the client entry, If it is locally connected then we will also
1367 disconnect the client here */
1368 if (remote_client->connection) {
1369 /* Remove locally conneted client */
1370 SilcSocketConnection sock = remote_client->connection;
1371 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
1372 silc_server_close_connection(server, sock);
1374 /* Update statistics */
1375 server->stat.clients--;
1376 if (server->stat.cell_clients)
1377 server->stat.cell_clients--;
1378 SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
1379 SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
1381 if (SILC_IS_LOCAL(remote_client)) {
1382 server->stat.my_clients--;
1383 silc_schedule_task_del_by_context(server->schedule, remote_client);
1384 silc_idlist_del_data(remote_client);
1387 /* Remove remote client */
1388 if (!silc_idlist_del_client(server->global_list, remote_client)) {
1389 /* Remove this client from watcher list if it is */
1390 silc_server_del_from_watcher_list(server, remote_client);
1391 silc_idlist_del_client(server->local_list, remote_client);
1395 silc_buffer_free(killer);
1396 silc_buffer_free(killed);
1401 SilcClientEntry client;
1402 SilcNotifyType notify;
1403 const char *new_nick;
1404 } WatcherNotifyContext;
1407 silc_server_check_watcher_list_foreach(void *key, void *context,
1410 WatcherNotifyContext *notify = user_context;
1411 SilcClientEntry entry = context;
1412 SilcSocketConnection sock;
1414 if (entry == notify->client)
1417 sock = silc_server_get_client_route(notify->server, NULL, 0, entry->id,
1420 SILC_LOG_DEBUG(("Sending WATCH notify to %s",
1421 silc_id_render(entry->id, SILC_ID_CLIENT)));
1423 /* Send the WATCH notify */
1424 silc_server_send_notify_watch(notify->server, sock, entry,
1426 notify->new_nick ? notify->new_nick :
1427 (const char *)notify->client->nickname,
1432 /* This function checks whether the `client' nickname is being watched
1433 by someone, and notifies the watcher of the notify change of notify
1434 type indicated by `notify'. */
1436 bool silc_server_check_watcher_list(SilcServer server,
1437 SilcClientEntry client,
1438 const char *new_nick,
1439 SilcNotifyType notify)
1441 unsigned char hash[16];
1442 WatcherNotifyContext n;
1444 SILC_LOG_DEBUG(("Checking watcher list %s",
1445 client->nickname ? client->nickname : (unsigned char *)""));
1447 /* If the watching is rejected by the client do nothing */
1448 if (client->mode & SILC_UMODE_REJECT_WATCHING)
1451 /* Make hash from the nick, or take it from Client ID */
1452 if (client->nickname) {
1454 memset(nick, 0, sizeof(nick));
1455 silc_to_lower(client->nickname, nick, sizeof(nick) - 1);
1456 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
1458 memset(hash, 0, sizeof(hash));
1459 memcpy(hash, client->id->hash, sizeof(client->id->hash));
1464 n.new_nick = new_nick;
1467 /* Send notify to all watchers */
1468 silc_hash_table_find_foreach(server->watcher_list, hash,
1469 silc_server_check_watcher_list_foreach, &n);
1474 /* Remove the `client' from watcher list. After calling this the `client'
1475 is not watching any nicknames. */
1477 bool silc_server_del_from_watcher_list(SilcServer server,
1478 SilcClientEntry client)
1480 SilcHashTableList htl;
1482 SilcClientEntry entry;
1485 silc_hash_table_list(server->watcher_list, &htl);
1486 while (silc_hash_table_get(&htl, &key, (void **)&entry)) {
1487 if (entry == client) {
1488 silc_hash_table_del_by_context(server->watcher_list, key, client);
1491 SILC_LOG_DEBUG(("Removing %s from WATCH list",
1492 silc_id_render(client->id, SILC_ID_CLIENT)));
1494 /* Now check whether there still exists entries with this key, if not
1495 then free the key to not leak memory. */
1496 if (!silc_hash_table_find(server->watcher_list, key, NULL, NULL))
1502 silc_hash_table_list_reset(&htl);
1507 /* Force the client indicated by `chl' to change the channel user mode
1508 on channel indicated by `channel' to `forced_mode'. */
1510 bool silc_server_force_cumode_change(SilcServer server,
1511 SilcSocketConnection sock,
1512 SilcChannelEntry channel,
1513 SilcChannelClientEntry chl,
1514 SilcUInt32 forced_mode)
1516 SilcBuffer idp1, idp2;
1517 unsigned char cumode[4];
1519 SILC_LOG_DEBUG(("Enforcing sender to change mode"));
1522 silc_server_send_notify_cumode(server, sock, FALSE, channel, forced_mode,
1523 server->id, SILC_ID_SERVER,
1524 chl->client->id, NULL);
1526 idp1 = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1527 idp2 = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
1528 SILC_PUT32_MSB(forced_mode, cumode);
1529 silc_server_send_notify_to_channel(server, sock, channel, FALSE,
1530 SILC_NOTIFY_TYPE_CUMODE_CHANGE,
1531 3, idp1->data, idp1->len,
1532 cumode, sizeof(cumode),
1533 idp2->data, idp2->len);
1534 silc_buffer_free(idp1);
1535 silc_buffer_free(idp2);
1540 /* Find active socket connection by the IP address and port indicated by
1541 `ip' and `port', and socket connection type of `type'. */
1543 SilcSocketConnection
1544 silc_server_find_socket_by_host(SilcServer server,
1545 SilcSocketType type,
1546 const char *ip, SilcUInt16 port)
1550 for (i = 0; i < server->config->param.connections_max; i++) {
1551 if (!server->sockets[i])
1553 if (!strcmp(server->sockets[i]->ip, ip) &&
1554 (!port || server->sockets[i]->port == port) &&
1555 server->sockets[i]->type == type)
1556 return server->sockets[i];