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 if (!(entry->data.status & SILC_IDLIST_STATUS_REGISTERED))
146 SILC_LOG_DEBUG(("Start"));
148 /* Allocate the hash table that holds the channels that require
149 channel key re-generation after we've removed this server's clients
150 from the channels. */
151 channels = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL,
153 clients = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL,
156 if (server_signoff) {
157 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
158 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
159 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) * (argc + 1));
160 argv_types = silc_realloc(argv_types, sizeof(*argv_types) * (argc + 1));
161 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
162 memcpy(argv[argc], idp->data, idp->len);
163 argv_lens[argc] = idp->len;
164 argv_types[argc] = argc + 1;
166 silc_buffer_free(idp);
169 if (silc_idcache_get_all(server->local_list->clients, &list)) {
171 if (silc_idcache_list_first(list, &id_cache)) {
173 client = (SilcClientEntry)id_cache->context;
174 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
175 if (!silc_idcache_list_next(list, &id_cache))
181 if (client->router != entry) {
182 if (!silc_idcache_list_next(list, &id_cache))
188 if (server_signoff) {
189 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
190 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
191 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
193 argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
195 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
196 memcpy(argv[argc], idp->data, idp->len);
197 argv_lens[argc] = idp->len;
198 argv_types[argc] = argc + 1;
200 silc_buffer_free(idp);
203 /* Update statistics */
204 server->stat.clients--;
205 if (server->stat.cell_clients)
206 server->stat.cell_clients--;
207 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
208 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
210 silc_server_remove_clients_channels(server, entry, clients,
212 silc_server_del_from_watcher_list(server, client);
214 /* Remove the client entry */
215 if (!server_signoff) {
216 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
217 id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
219 silc_idlist_del_client(server->local_list, client);
222 if (!silc_idcache_list_next(list, &id_cache))
226 silc_idcache_list_free(list);
229 if (silc_idcache_get_all(server->global_list->clients, &list)) {
231 if (silc_idcache_list_first(list, &id_cache)) {
233 client = (SilcClientEntry)id_cache->context;
234 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
235 if (!silc_idcache_list_next(list, &id_cache))
241 if (client->router != entry) {
242 if (!silc_idcache_list_next(list, &id_cache))
248 if (server_signoff) {
249 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
250 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
251 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
253 argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
255 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
256 memcpy(argv[argc], idp->data, idp->len);
257 argv_lens[argc] = idp->len;
258 argv_types[argc] = argc + 1;
260 silc_buffer_free(idp);
263 /* Update statistics */
264 server->stat.clients--;
265 if (server->stat.cell_clients)
266 server->stat.cell_clients--;
267 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
268 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
270 silc_server_remove_clients_channels(server, entry, clients,
272 silc_server_del_from_watcher_list(server, client);
274 /* Remove the client entry */
275 if (!server_signoff) {
276 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
277 id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
279 silc_idlist_del_client(server->global_list, client);
282 if (!silc_idcache_list_next(list, &id_cache))
286 silc_idcache_list_free(list);
289 /* Send the SERVER_SIGNOFF notify */
290 if (server_signoff) {
291 SilcBuffer args, not;
293 SILC_LOG_DEBUG(("Sending SERVER_SIGNOFF for %d clients",
296 /* Send SERVER_SIGNOFF notify to our primary router */
297 if (server->router != entry) {
298 args = silc_argument_payload_encode(1, argv, argv_lens,
300 silc_server_send_notify_args(server, SILC_PRIMARY_ROUTE(server),
301 SILC_BROADCAST(server),
302 SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
304 silc_buffer_free(args);
307 /* Send to local clients. We also send the list of client ID's that
308 is to be removed for those servers that would like to use that list. */
309 args = silc_argument_payload_encode(argc, argv, argv_lens,
311 not = silc_notify_payload_encode_args(SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
313 silc_server_packet_send_clients(server, clients,
314 SILC_PACKET_NOTIFY, 0, FALSE,
315 not->data, not->len, FALSE);
317 silc_buffer_free(args);
318 silc_buffer_free(not);
319 for (i = 0; i < argc; i++)
322 silc_free(argv_lens);
323 silc_free(argv_types);
324 silc_hash_table_free(clients);
327 /* We must now re-generate the channel key for all channels that had
328 this server's client(s) on the channel. As they left the channel we
329 must re-generate the channel key. */
330 silc_hash_table_list(channels, &htl);
331 while (silc_hash_table_get(&htl, NULL, (void **)&channel)) {
332 if (!silc_server_create_channel_key(server, channel, 0)) {
333 silc_hash_table_list_reset(&htl);
334 silc_hash_table_free(channels);
338 /* Do not send the channel key if private channel key mode is set */
339 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY)
342 silc_server_send_channel_key(server, NULL, channel,
343 server->server_type == SILC_ROUTER ?
344 FALSE : !server->standalone);
346 silc_hash_table_list_reset(&htl);
347 silc_hash_table_free(channels);
352 static SilcServerEntry
353 silc_server_update_clients_by_real_server(SilcServer server,
354 SilcServerEntry from,
355 SilcClientEntry client,
357 SilcIDCacheEntry client_cache)
359 SilcServerEntry server_entry;
360 SilcIDCacheEntry id_cache = NULL;
361 SilcIDCacheList list;
363 if (!silc_idcache_get_all(server->local_list->servers, &list))
366 if (silc_idcache_list_first(list, &id_cache)) {
368 server_entry = (SilcServerEntry)id_cache->context;
369 if (server_entry != from &&
370 SILC_ID_COMPARE(server_entry->id, client->id,
371 client->id->ip.data_len)) {
372 SILC_LOG_DEBUG(("Found (local) %s",
373 silc_id_render(server_entry->id, SILC_ID_SERVER)));
375 if (!server_entry->data.send_key && server_entry->router) {
376 SILC_LOG_DEBUG(("Server not locally connected, use its router"));
377 /* If the client is not marked as local then move it to local list
378 since the server is local. */
380 SILC_LOG_DEBUG(("Moving client to local list"));
381 silc_idcache_add(server->local_list->clients, client_cache->name,
382 client_cache->id, client_cache->context,
383 client_cache->expire, NULL);
384 silc_idcache_del_by_context(server->global_list->clients, client);
386 server_entry = server_entry->router;
388 /* If the client is not marked as local then move it to local list
389 since the server is local. */
390 if (server_entry->server_type != SILC_BACKUP_ROUTER && !local) {
391 SILC_LOG_DEBUG(("Moving client to local list"));
392 silc_idcache_add(server->local_list->clients, client_cache->name,
393 client_cache->id, client_cache->context,
394 client_cache->expire, NULL);
395 silc_idcache_del_by_context(server->global_list->clients, client);
399 silc_idcache_list_free(list);
403 if (!silc_idcache_list_next(list, &id_cache))
408 silc_idcache_list_free(list);
410 if (!silc_idcache_get_all(server->global_list->servers, &list))
413 if (silc_idcache_list_first(list, &id_cache)) {
415 server_entry = (SilcServerEntry)id_cache->context;
416 if (server_entry != from &&
417 SILC_ID_COMPARE(server_entry->id, client->id,
418 client->id->ip.data_len)) {
419 SILC_LOG_DEBUG(("Found (global) %s",
420 silc_id_render(server_entry->id, SILC_ID_SERVER)));
422 if (!server_entry->data.send_key && server_entry->router) {
423 SILC_LOG_DEBUG(("Server not locally connected, use its router"));
424 /* If the client is marked as local then move it to global list
425 since the server is global. */
427 SILC_LOG_DEBUG(("Moving client to global list"));
428 silc_idcache_add(server->global_list->clients, client_cache->name,
429 client_cache->id, client_cache->context,
430 client_cache->expire, NULL);
431 silc_idcache_del_by_context(server->local_list->clients, client);
433 server_entry = server_entry->router;
435 /* If the client is marked as local then move it to global list
436 since the server is global. */
437 if (server_entry->server_type != SILC_BACKUP_ROUTER && local) {
438 SILC_LOG_DEBUG(("Moving client to global list"));
439 silc_idcache_add(server->global_list->clients, client_cache->name,
440 client_cache->id, client_cache->context,
441 client_cache->expire, NULL);
442 silc_idcache_del_by_context(server->local_list->clients, client);
446 silc_idcache_list_free(list);
450 if (!silc_idcache_list_next(list, &id_cache))
455 silc_idcache_list_free(list);
460 /* Updates the clients that are originated from the `from' to be originated
461 from the `to'. If the `resolve_real_server' is TRUE then this will
462 attempt to figure out which clients really are originated from the
463 `from' and which are originated from a server that we have connection
464 to, when we've acting as backup router. If it is FALSE the `to' will
465 be the new source. This function also removes the clients that are
466 *really* originated from `from' if `remove_from' is TRUE. These are
467 clients that the `from' owns, and not just clients that are behind
468 the `from'. If `from' is NULL then all non-local clients are switched
471 void silc_server_update_clients_by_server(SilcServer server,
472 SilcServerEntry from,
474 bool resolve_real_server,
477 SilcIDCacheList list = NULL;
478 SilcIDCacheEntry id_cache = NULL;
479 SilcClientEntry client = NULL;
483 SILC_LOG_DEBUG(("Updating %s", silc_id_render(from->id,
486 SILC_LOG_DEBUG(("to %s", silc_id_render(to->id,
490 if (silc_idcache_get_all(server->global_list->clients, &list)) {
491 if (silc_idcache_list_first(list, &id_cache)) {
493 client = (SilcClientEntry)id_cache->context;
495 /* If entry is disabled skip it. If entry is local to us, do not
496 switch it to anyone else, it is ours so skip it. */
497 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
498 SILC_IS_LOCAL(client)) {
499 if (!silc_idcache_list_next(list, &id_cache))
505 SILC_LOG_DEBUG(("Client (global) %s",
506 silc_id_render(client->id, SILC_ID_CLIENT)));
508 SILC_LOG_DEBUG(("Client->router (global) %s",
509 silc_id_render(client->router->id, SILC_ID_SERVER)));
512 if (client->router == from) {
513 /* Skip clients that are *really* owned by the `from' */
514 if (remove_from && SILC_ID_COMPARE(from->id, client->id,
515 client->id->ip.data_len)) {
516 SILC_LOG_DEBUG(("Found really owned client, skip it"));
517 if (!silc_idcache_list_next(list, &id_cache))
523 if (resolve_real_server) {
525 silc_server_update_clients_by_real_server(server, from, client,
527 if (!client->router) {
528 if (server->server_type == SILC_ROUTER)
529 client->router = from;
538 /* All are changed */
543 SILC_LOG_DEBUG(("Client changed to %s",
544 silc_id_render(client->router->id, SILC_ID_CLIENT)));
546 if (!silc_idcache_list_next(list, &id_cache))
550 silc_idcache_list_free(list);
554 if (silc_idcache_get_all(server->local_list->clients, &list)) {
555 if (silc_idcache_list_first(list, &id_cache)) {
557 client = (SilcClientEntry)id_cache->context;
559 /* If entry is disabled skip it. If entry is local to us, do not
560 switch it to anyone else, it is ours so skip it. */
561 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
562 SILC_IS_LOCAL(client)) {
563 if (!silc_idcache_list_next(list, &id_cache))
569 SILC_LOG_DEBUG(("Client (local) %s",
570 silc_id_render(client->id, SILC_ID_CLIENT)));
572 SILC_LOG_DEBUG(("Client->router (local) %s",
573 silc_id_render(client->router->id, SILC_ID_SERVER)));
576 if (client->router == from) {
577 /* Skip clients that are *really* owned by the `from' */
578 if (remove_from && SILC_ID_COMPARE(from->id, client->id,
579 client->id->ip.data_len)) {
580 SILC_LOG_DEBUG(("Found really owned client, skip it"));
581 if (!silc_idcache_list_next(list, &id_cache))
587 if (resolve_real_server) {
589 silc_server_update_clients_by_real_server(server, from, client,
592 client->router = from;
598 /* All are changed */
603 SILC_LOG_DEBUG(("Client changed to %s",
604 silc_id_render(client->router->id, SILC_ID_CLIENT)));
606 if (!silc_idcache_list_next(list, &id_cache))
610 silc_idcache_list_free(list);
614 /* Now remove the clients that are still marked as orignated from the
615 `from'. These are the clients that really was owned by the `from' and
616 not just exist behind the `from'. */
617 silc_server_remove_clients_by_server(server, from, TRUE);
620 /* Updates servers that are from `from' to be originated from `to'. This
621 will also update the server's connection to `to's connection. */
623 void silc_server_update_servers_by_server(SilcServer server,
624 SilcServerEntry from,
627 SilcIDCacheList list = NULL;
628 SilcIDCacheEntry id_cache = NULL;
629 SilcServerEntry server_entry = NULL;
631 SILC_LOG_DEBUG(("Updating servers"));
633 if (silc_idcache_get_all(server->local_list->servers, &list)) {
634 if (silc_idcache_list_first(list, &id_cache)) {
636 server_entry = (SilcServerEntry)id_cache->context;
638 /* If entry is local to us, do not switch it to any anyone else,
640 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
641 server_entry == from) {
642 if (!silc_idcache_list_next(list, &id_cache))
648 /* If we are standalone router, any server that is not directly
649 connected to cannot exist anymore. If we are not standalone
650 we update it correctly. */
651 if (server->server_type == SILC_ROUTER && server->standalone) {
652 silc_server_backup_del(server, server_entry);
653 silc_server_backup_replaced_del(server, server_entry);
654 silc_idlist_del_data(server_entry);
655 silc_idlist_del_server(server->local_list, server_entry);
656 server->stat.servers--;
657 server->stat.cell_servers--;
659 /* XXX if we are not standalone, do a check from local config
660 whether this server is in our cell, but not connected to
661 us (in which case we must remove it). */
663 if (server_entry->router == from) {
664 SILC_LOG_DEBUG(("Updating server (local) %s",
665 server_entry->server_name ?
666 server_entry->server_name : ""));
667 server_entry->router = to;
668 server_entry->connection = to->connection;
672 if (!silc_idcache_list_next(list, &id_cache))
676 silc_idcache_list_free(list);
679 if (silc_idcache_get_all(server->global_list->servers, &list)) {
680 if (silc_idcache_list_first(list, &id_cache)) {
682 server_entry = (SilcServerEntry)id_cache->context;
684 /* If entry is local to us, do not switch it to anyone else,
686 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
687 server_entry == from) {
688 if (!silc_idcache_list_next(list, &id_cache))
694 /* If we are standalone router, any server that is not directly
695 connected to cannot exist anymore. If we are not standalone
696 we update it correctly. */
697 if (server->server_type == SILC_ROUTER && server->standalone) {
698 silc_server_backup_del(server, server_entry);
699 silc_server_backup_replaced_del(server, server_entry);
700 silc_idlist_del_data(server_entry);
701 silc_idlist_del_server(server->global_list, server_entry);
702 server->stat.servers--;
703 server->stat.cell_servers--;
705 /* XXX if we are not standalone, do a check from local config
706 whether this server is in our cell, but not connected to
707 us (in which case we must remove it). */
709 if (server_entry->router == from) {
710 SILC_LOG_DEBUG(("Updating server (global) %s",
711 server_entry->server_name ?
712 server_entry->server_name : ""));
713 server_entry->router = to;
714 server_entry->connection = to->connection;
718 if (!silc_idcache_list_next(list, &id_cache))
722 silc_idcache_list_free(list);
727 /* Toggles the enabled/disabled status of local server connections. Packets
728 can be sent to the servers when `toggle_enabled' is TRUE and will be
729 dropped if `toggle_enabled' is FALSE, after this function is called. */
731 void silc_server_local_servers_toggle_enabled(SilcServer server,
734 SilcIDCacheList list = NULL;
735 SilcIDCacheEntry id_cache = NULL;
736 SilcServerEntry server_entry = NULL;
738 if (silc_idcache_get_all(server->local_list->servers, &list)) {
739 if (silc_idcache_list_first(list, &id_cache)) {
741 server_entry = (SilcServerEntry)id_cache->context;
742 if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry) {
743 if (!silc_idcache_list_next(list, &id_cache))
750 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
752 server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
754 if (!silc_idcache_list_next(list, &id_cache))
758 silc_idcache_list_free(list);
761 if (silc_idcache_get_all(server->global_list->servers, &list)) {
762 if (silc_idcache_list_first(list, &id_cache)) {
764 server_entry = (SilcServerEntry)id_cache->context;
765 if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry) {
766 if (!silc_idcache_list_next(list, &id_cache))
773 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
775 server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
777 if (!silc_idcache_list_next(list, &id_cache))
781 silc_idcache_list_free(list);
784 /* Removes channels that are from `from. */
786 void silc_server_remove_channels_by_server(SilcServer server,
787 SilcServerEntry from)
789 SilcIDCacheList list = NULL;
790 SilcIDCacheEntry id_cache = NULL;
791 SilcChannelEntry channel = NULL;
793 SILC_LOG_DEBUG(("Removing channels by server"));
795 if (silc_idcache_get_all(server->global_list->channels, &list)) {
796 if (silc_idcache_list_first(list, &id_cache)) {
798 channel = (SilcChannelEntry)id_cache->context;
799 if (channel->router == from)
800 silc_idlist_del_channel(server->global_list, channel);
801 if (!silc_idcache_list_next(list, &id_cache))
805 silc_idcache_list_free(list);
809 /* Updates channels that are from `from' to be originated from `to'. */
811 void silc_server_update_channels_by_server(SilcServer server,
812 SilcServerEntry from,
815 SilcIDCacheList list = NULL;
816 SilcIDCacheEntry id_cache = NULL;
817 SilcChannelEntry channel = NULL;
819 SILC_LOG_DEBUG(("Updating channels by server"));
821 if (silc_idcache_get_all(server->global_list->channels, &list)) {
822 if (silc_idcache_list_first(list, &id_cache)) {
824 channel = (SilcChannelEntry)id_cache->context;
825 if (channel->router == from)
826 channel->router = to;
827 if (!silc_idcache_list_next(list, &id_cache))
831 silc_idcache_list_free(list);
835 /* Checks whether given channel has global users. If it does this returns
836 TRUE and FALSE if there is only locally connected clients on the channel. */
838 bool silc_server_channel_has_global(SilcChannelEntry channel)
840 SilcChannelClientEntry chl;
841 SilcHashTableList htl;
843 silc_hash_table_list(channel->user_list, &htl);
844 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
845 if (chl->client->router) {
846 silc_hash_table_list_reset(&htl);
850 silc_hash_table_list_reset(&htl);
855 /* Checks whether given channel has locally connected users. If it does this
856 returns TRUE and FALSE if there is not one locally connected client. */
858 bool silc_server_channel_has_local(SilcChannelEntry channel)
860 SilcChannelClientEntry chl;
861 SilcHashTableList htl;
863 silc_hash_table_list(channel->user_list, &htl);
864 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
865 if (!chl->client->router) {
866 silc_hash_table_list_reset(&htl);
870 silc_hash_table_list_reset(&htl);
875 /* This function removes the channel and all users on the channel, unless
876 the channel is permanent. In this case the channel is disabled but all
877 users are removed from the channel. Returns TRUE if the channel is
878 destroyed totally, and FALSE if it is permanent and remains. */
880 bool silc_server_channel_delete(SilcServer server,
881 SilcChannelEntry channel)
883 SilcChannelClientEntry chl;
884 SilcHashTableList htl;
885 bool delchan = !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH);
888 SILC_LOG_DEBUG(("Deleting %s channel", channel->channel_name));
890 /* Update statistics */
891 if (server->server_type == SILC_ROUTER)
892 server->stat.chanclients -= channel->user_count;
894 /* Totally delete the channel and all users on the channel. The
895 users are deleted automatically in silc_idlist_del_channel. */
896 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
897 if (silc_idlist_del_channel(server->local_list, channel)) {
898 server->stat.my_channels--;
899 if (server->server_type == SILC_ROUTER) {
900 server->stat.channels--;
901 server->stat.cell_channels--;
904 if (silc_idlist_del_channel(server->global_list, channel))
905 if (server->server_type == SILC_ROUTER)
906 server->stat.channels--;
912 /* Channel is permanent, do not remove it, remove only users */
913 channel->disabled = TRUE;
914 silc_hash_table_list(channel->user_list, &htl);
915 while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
916 silc_hash_table_del(chl->client->channels, channel);
917 silc_hash_table_del(channel->user_list, chl->client);
918 channel->user_count--;
920 /* Update statistics */
921 if (SILC_IS_LOCAL(chl->client))
922 server->stat.my_chanclients--;
923 if (server->server_type == SILC_ROUTER) {
924 server->stat.cell_chanclients--;
925 server->stat.chanclients--;
930 silc_hash_table_list_reset(&htl);
932 SILC_LOG_DEBUG(("Channel %s remains", channel->channel_name));
937 /* Returns TRUE if the given client is on the channel. FALSE if not.
938 This works because we assure that the user list on the channel is
939 always in up to date thus we can only check the channel list from
940 `client' which is faster than checking the user list from `channel'. */
942 bool silc_server_client_on_channel(SilcClientEntry client,
943 SilcChannelEntry channel,
944 SilcChannelClientEntry *chl)
946 if (!client || !channel)
949 return silc_hash_table_find(client->channels, channel, NULL,
953 /* Checks string for bad characters and returns TRUE if they are found. */
955 bool silc_server_name_bad_chars(const char *name, SilcUInt32 name_len)
959 for (i = 0; i < name_len; i++) {
960 if (!isascii(name[i]))
962 if (name[i] <= 32) return TRUE;
963 if (name[i] == ' ') return TRUE;
964 if (name[i] == '*') return TRUE;
965 if (name[i] == '?') return TRUE;
966 if (name[i] == ',') return TRUE;
972 /* Modifies the `name' if it includes bad characters and returns new
973 allocated name that does not include bad characters. */
975 char *silc_server_name_modify_bad(const char *name, SilcUInt32 name_len)
978 char *newname = strdup(name);
980 for (i = 0; i < name_len; i++) {
981 if (!isascii(newname[i])) newname[i] = '_';
982 if (newname[i] <= 32) newname[i] = '_';
983 if (newname[i] == ' ') newname[i] = '_';
984 if (newname[i] == '*') newname[i] = '_';
985 if (newname[i] == '?') newname[i] = '_';
986 if (newname[i] == ',') newname[i] = '_';
992 /* Find number of sockets by IP address indicated by `ip'. Returns 0 if
993 socket connections with the IP address does not exist. */
995 SilcUInt32 silc_server_num_sockets_by_ip(SilcServer server, const char *ip,
1000 for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
1001 if (server->sockets[i] && !strcmp(server->sockets[i]->ip, ip) &&
1002 server->sockets[i]->type == type)
1009 /* Find number of sockets by IP address indicated by remote host, indicatd
1010 by `ip' or `hostname', `port', and `type'. Returns 0 if socket connections
1011 does not exist. If `ip' is provided then `hostname' is ignored. */
1013 SilcUInt32 silc_server_num_sockets_by_remote(SilcServer server,
1015 const char *hostname,
1017 SilcSocketType type)
1021 if (!ip && !hostname)
1024 for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
1025 if (server->sockets[i] &&
1026 ((ip && !strcmp(server->sockets[i]->ip, ip)) ||
1027 (hostname && !strcmp(server->sockets[i]->hostname, hostname))) &&
1028 server->sockets[i]->port == port &&
1029 server->sockets[i]->type == type)
1036 /* Finds locally cached public key by the public key received in the SKE.
1037 If we have it locally cached then we trust it and will use it in the
1038 authentication protocol. Returns the locally cached public key or NULL
1039 if we do not find the public key. */
1041 SilcPublicKey silc_server_find_public_key(SilcServer server,
1042 SilcHashTable local_public_keys,
1043 SilcPublicKey remote_public_key)
1045 SilcPublicKey cached_key;
1047 SILC_LOG_DEBUG(("Find remote public key (%d keys in local cache)",
1048 silc_hash_table_count(local_public_keys)));
1050 if (!silc_hash_table_find_ext(local_public_keys, remote_public_key,
1051 (void **)&cached_key, NULL,
1052 silc_hash_public_key, NULL,
1053 silc_hash_public_key_compare, NULL)) {
1054 SILC_LOG_ERROR(("Public key not found"));
1058 SILC_LOG_DEBUG(("Found public key"));
1063 /* This returns the first public key from the table of public keys. This
1064 is used only in cases where single public key exists in the table and
1065 we want to get a pointer to it. For public key tables that has multiple
1066 keys in it the silc_server_find_public_key must be used. */
1068 SilcPublicKey silc_server_get_public_key(SilcServer server,
1069 SilcHashTable local_public_keys)
1071 SilcPublicKey cached_key;
1072 SilcHashTableList htl;
1074 SILC_LOG_DEBUG(("Start"));
1076 assert(silc_hash_table_count(local_public_keys) < 2);
1078 silc_hash_table_list(local_public_keys, &htl);
1079 if (!silc_hash_table_get(&htl, NULL, (void **)&cached_key))
1081 silc_hash_table_list_reset(&htl);
1086 /* Check whether the connection `sock' is allowed to connect to us. This
1087 checks for example whether there is too much connections for this host,
1088 and required version for the host etc. */
1090 bool silc_server_connection_allowed(SilcServer server,
1091 SilcSocketConnection sock,
1092 SilcSocketType type,
1093 SilcServerConfigConnParams *global,
1094 SilcServerConfigConnParams *params,
1097 SilcUInt32 conn_number = (type == SILC_SOCKET_TYPE_CLIENT ?
1098 server->stat.my_clients :
1099 type == SILC_SOCKET_TYPE_SERVER ?
1100 server->stat.my_servers :
1101 server->stat.my_routers);
1102 SilcUInt32 num_sockets, max_hosts, max_per_host;
1103 SilcUInt32 r_protocol_version, l_protocol_version;
1104 SilcUInt32 r_software_version, l_software_version;
1105 char *r_vendor_version = NULL, *l_vendor_version;
1107 SILC_LOG_DEBUG(("Checking whether connection is allowed"));
1111 l_protocol_version =
1112 silc_version_to_num(params && params->version_protocol ?
1113 params->version_protocol :
1114 global->version_protocol);
1115 l_software_version =
1116 silc_version_to_num(params && params->version_software ?
1117 params->version_software :
1118 global->version_software);
1119 l_vendor_version = (params && params->version_software_vendor ?
1120 params->version_software_vendor :
1121 global->version_software_vendor);
1123 if (ske && silc_ske_parse_version(ske, &r_protocol_version, NULL,
1124 &r_software_version, NULL,
1125 &r_vendor_version)) {
1126 sock->version = r_protocol_version;
1128 /* Match protocol version */
1129 if (l_protocol_version && r_protocol_version &&
1130 r_protocol_version < l_protocol_version) {
1131 SILC_LOG_INFO(("Connection %s (%s) is too old version",
1132 sock->hostname, sock->ip));
1133 silc_server_disconnect_remote(server, sock,
1134 SILC_STATUS_ERR_BAD_VERSION,
1135 "You support too old protocol version");
1139 /* Math software version */
1140 if (l_software_version && r_software_version &&
1141 r_software_version < l_software_version) {
1142 SILC_LOG_INFO(("Connection %s (%s) is too old version",
1143 sock->hostname, sock->ip));
1144 silc_server_disconnect_remote(server, sock,
1145 SILC_STATUS_ERR_BAD_VERSION,
1146 "You support too old software version");
1150 /* Regex match vendor version */
1151 if (l_vendor_version && r_vendor_version &&
1152 !silc_string_match(l_vendor_version, r_vendor_version)) {
1153 SILC_LOG_INFO(("Connection %s (%s) is unsupported version",
1154 sock->hostname, sock->ip));
1155 silc_server_disconnect_remote(server, sock,
1156 SILC_STATUS_ERR_BAD_VERSION,
1157 "Your software is not supported");
1161 silc_free(r_vendor_version);
1163 /* Check for maximum connections limit */
1165 num_sockets = silc_server_num_sockets_by_ip(server, sock->ip, type);
1166 max_hosts = (params ? params->connections_max : global->connections_max);
1167 max_per_host = (params ? params->connections_max_per_host :
1168 global->connections_max_per_host);
1170 if (max_hosts && conn_number >= max_hosts) {
1171 SILC_LOG_INFO(("Server is full, closing %s (%s) connection",
1172 sock->hostname, sock->ip));
1173 silc_server_disconnect_remote(server, sock,
1174 SILC_STATUS_ERR_RESOURCE_LIMIT,
1175 "Server is full, try again later");
1179 if (num_sockets >= max_per_host) {
1180 SILC_LOG_INFO(("Too many connections from %s (%s), closing connection",
1181 sock->hostname, sock->ip));
1182 silc_server_disconnect_remote(server, sock,
1183 SILC_STATUS_ERR_RESOURCE_LIMIT,
1184 "Too many connections from your host");
1191 /* Checks that client has rights to add or remove channel modes. If any
1192 of the checks fails FALSE is returned. */
1194 bool silc_server_check_cmode_rights(SilcServer server,
1195 SilcChannelEntry channel,
1196 SilcChannelClientEntry client,
1199 bool is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1200 bool is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1202 /* Check whether has rights to change anything */
1203 if (!is_op && !is_fo)
1206 /* Check whether has rights to change everything */
1210 /* Founder implies operator */
1214 /* We know that client is channel operator, check that they are not
1215 changing anything that requires channel founder rights. Rest of the
1216 modes are available automatically for channel operator. */
1218 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1219 if (is_op && !is_fo)
1222 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1223 if (is_op && !is_fo)
1228 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1229 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
1230 if (is_op && !is_fo)
1234 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1235 if (is_op && !is_fo)
1240 if (mode & SILC_CHANNEL_MODE_CIPHER) {
1241 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
1242 if (is_op && !is_fo)
1246 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1247 if (is_op && !is_fo)
1252 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1253 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
1254 if (is_op && !is_fo)
1258 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1259 if (is_op && !is_fo)
1264 if (mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1265 if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS)) {
1266 if (is_op && !is_fo)
1270 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1271 if (is_op && !is_fo)
1276 if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1277 if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS)) {
1278 if (is_op && !is_fo)
1282 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1283 if (is_op && !is_fo)
1291 /* Check that the client has rights to change its user mode. Returns
1292 FALSE if setting some mode is not allowed. */
1294 bool silc_server_check_umode_rights(SilcServer server,
1295 SilcClientEntry client,
1298 bool server_op = FALSE, router_op = FALSE;
1300 if (mode & SILC_UMODE_SERVER_OPERATOR) {
1301 /* Cannot set server operator mode (must use OPER command) */
1302 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR))
1305 /* Remove the server operator rights */
1306 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
1310 if (mode & SILC_UMODE_ROUTER_OPERATOR) {
1311 /* Cannot set router operator mode (must use SILCOPER command) */
1312 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR))
1315 /* Remove the router operator rights */
1316 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
1321 SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR);
1323 SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR);
1328 /* This function is used to send the notify packets and motd to the
1329 incoming client connection. */
1331 void silc_server_send_connect_notifys(SilcServer server,
1332 SilcSocketConnection sock,
1333 SilcClientEntry client)
1335 SilcIDListData idata = (SilcIDListData)client;
1337 SILC_LOG_DEBUG(("Send welcome notifys"));
1339 /* Send some nice info to the client */
1340 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1341 ("Welcome to the SILC Network %s",
1343 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1344 ("Your host is %s, running version %s",
1345 server->server_name, server_version));
1347 if (server->server_type == SILC_ROUTER) {
1348 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1349 ("There are %d clients, %d servers and %d "
1350 "routers in SILC Network",
1351 server->stat.clients, server->stat.servers + 1,
1352 server->stat.routers));
1354 if (server->stat.clients && server->stat.servers + 1)
1355 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1356 ("There are %d clients, %d servers and %d "
1357 "routers in SILC Network",
1358 server->stat.clients, server->stat.servers + 1,
1359 (server->standalone ? 0 :
1360 !server->stat.routers ? 1 :
1361 server->stat.routers)));
1364 if (server->stat.cell_clients && server->stat.cell_servers + 1)
1365 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1366 ("There are %d clients on %d server in our cell",
1367 server->stat.cell_clients,
1368 server->stat.cell_servers + 1));
1369 if (server->server_type == SILC_ROUTER) {
1370 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1371 ("I have %d clients, %d channels, %d servers and "
1373 server->stat.my_clients,
1374 server->stat.my_channels,
1375 server->stat.my_servers,
1376 server->stat.my_routers));
1378 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1379 ("I have %d clients and %d channels formed",
1380 server->stat.my_clients,
1381 server->stat.my_channels));
1384 if (server->stat.server_ops || server->stat.router_ops)
1385 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1386 ("There are %d server operators and %d router "
1388 server->stat.server_ops,
1389 server->stat.router_ops));
1390 if (server->stat.my_router_ops + server->stat.my_server_ops)
1391 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1392 ("I have %d operators online",
1393 server->stat.my_router_ops +
1394 server->stat.my_server_ops));
1396 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1397 ("Your connection is secured with %s cipher, "
1398 "key length %d bits",
1399 idata->send_key->cipher->name,
1400 idata->send_key->cipher->key_len));
1401 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1402 ("Your current nickname is %s",
1406 silc_server_send_motd(server, sock);
1409 /* Kill the client indicated by `remote_client' sending KILLED notify
1410 to the client, to all channels client has joined and to primary
1411 router if needed. The killed client is also removed from all channels. */
1413 void silc_server_kill_client(SilcServer server,
1414 SilcClientEntry remote_client,
1415 const char *comment,
1417 SilcIdType killer_id_type)
1419 SilcBuffer killed, killer;
1421 SILC_LOG_DEBUG(("Killing client %s",
1422 silc_id_render(remote_client->id, SILC_ID_CLIENT)));
1424 /* Send the KILL notify packets. First send it to the channel, then
1425 to our primary router and then directly to the client who is being
1426 killed right now. */
1428 killed = silc_id_payload_encode(remote_client->id, SILC_ID_CLIENT);
1429 killer = silc_id_payload_encode(killer_id, killer_id_type);
1431 /* Send KILLED notify to the channels. It is not sent to the client
1432 as it will be sent differently destined directly to the client and not
1434 silc_server_send_notify_on_channels(server, remote_client,
1435 remote_client, SILC_NOTIFY_TYPE_KILLED,
1436 3, killed->data, killed->len,
1437 comment, comment ? strlen(comment) : 0,
1438 killer->data, killer->len);
1440 /* Send KILLED notify to primary route */
1441 silc_server_send_notify_killed(server, SILC_PRIMARY_ROUTE(server),
1442 SILC_BROADCAST(server), remote_client->id,
1443 comment, killer_id, killer_id_type);
1445 /* Send KILLED notify to the client directly */
1446 if (remote_client->connection || remote_client->router)
1447 silc_server_send_notify_killed(server, remote_client->connection ?
1448 remote_client->connection :
1449 remote_client->router->connection, FALSE,
1450 remote_client->id, comment,
1451 killer_id, killer_id_type);
1453 /* Remove the client from all channels. This generates new keys to the
1454 channels as well. */
1455 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
1458 /* Remove the client entry, If it is locally connected then we will also
1459 disconnect the client here */
1460 if (remote_client->connection) {
1461 /* Remove locally conneted client */
1462 SilcSocketConnection sock = remote_client->connection;
1463 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
1464 silc_server_close_connection(server, sock);
1466 /* Update statistics */
1467 server->stat.clients--;
1468 if (server->stat.cell_clients)
1469 server->stat.cell_clients--;
1470 SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
1471 SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
1473 if (SILC_IS_LOCAL(remote_client)) {
1474 server->stat.my_clients--;
1475 silc_schedule_task_del_by_context(server->schedule, remote_client);
1476 silc_idlist_del_data(remote_client);
1479 /* Remove remote client */
1480 if (!silc_idlist_del_client(server->global_list, remote_client)) {
1481 /* Remove this client from watcher list if it is */
1482 silc_server_del_from_watcher_list(server, remote_client);
1483 silc_idlist_del_client(server->local_list, remote_client);
1487 silc_buffer_free(killer);
1488 silc_buffer_free(killed);
1493 SilcClientEntry client;
1494 SilcNotifyType notify;
1495 const char *new_nick;
1496 } WatcherNotifyContext;
1499 silc_server_check_watcher_list_foreach(void *key, void *context,
1502 WatcherNotifyContext *notify = user_context;
1503 SilcClientEntry entry = context;
1504 SilcSocketConnection sock;
1506 if (entry == notify->client)
1509 sock = silc_server_get_client_route(notify->server, NULL, 0, entry->id,
1512 SILC_LOG_DEBUG(("Sending WATCH notify to %s",
1513 silc_id_render(entry->id, SILC_ID_CLIENT)));
1515 /* Send the WATCH notify */
1516 silc_server_send_notify_watch(notify->server, sock, entry,
1518 notify->new_nick ? notify->new_nick :
1519 (const char *)notify->client->nickname,
1524 /* This function checks whether the `client' nickname is being watched
1525 by someone, and notifies the watcher of the notify change of notify
1526 type indicated by `notify'. */
1528 bool silc_server_check_watcher_list(SilcServer server,
1529 SilcClientEntry client,
1530 const char *new_nick,
1531 SilcNotifyType notify)
1533 unsigned char hash[16];
1534 WatcherNotifyContext n;
1536 SILC_LOG_DEBUG(("Checking watcher list %s",
1537 client->nickname ? client->nickname : (unsigned char *)""));
1539 /* If the watching is rejected by the client do nothing */
1540 if (client->mode & SILC_UMODE_REJECT_WATCHING)
1543 /* Make hash from the nick, or take it from Client ID */
1544 if (client->nickname) {
1546 memset(nick, 0, sizeof(nick));
1547 silc_to_lower(client->nickname, nick, sizeof(nick) - 1);
1548 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
1550 memset(hash, 0, sizeof(hash));
1551 memcpy(hash, client->id->hash, sizeof(client->id->hash));
1556 n.new_nick = new_nick;
1559 /* Send notify to all watchers */
1560 silc_hash_table_find_foreach(server->watcher_list, hash,
1561 silc_server_check_watcher_list_foreach, &n);
1566 /* Remove the `client' from watcher list. After calling this the `client'
1567 is not watching any nicknames. */
1569 bool silc_server_del_from_watcher_list(SilcServer server,
1570 SilcClientEntry client)
1572 SilcHashTableList htl;
1574 SilcClientEntry entry;
1577 silc_hash_table_list(server->watcher_list, &htl);
1578 while (silc_hash_table_get(&htl, &key, (void **)&entry)) {
1579 if (entry == client) {
1580 silc_hash_table_del_by_context(server->watcher_list, key, client);
1583 SILC_LOG_DEBUG(("Removing %s from WATCH list",
1584 silc_id_render(client->id, SILC_ID_CLIENT)));
1586 /* Now check whether there still exists entries with this key, if not
1587 then free the key to not leak memory. */
1588 if (!silc_hash_table_find(server->watcher_list, key, NULL, NULL))
1594 silc_hash_table_list_reset(&htl);
1599 /* Force the client indicated by `chl' to change the channel user mode
1600 on channel indicated by `channel' to `forced_mode'. */
1602 bool silc_server_force_cumode_change(SilcServer server,
1603 SilcSocketConnection sock,
1604 SilcChannelEntry channel,
1605 SilcChannelClientEntry chl,
1606 SilcUInt32 forced_mode)
1608 SilcBuffer idp1, idp2;
1609 unsigned char cumode[4];
1611 SILC_LOG_DEBUG(("Enforcing sender to change mode"));
1614 silc_server_send_notify_cumode(server, sock, FALSE, channel, forced_mode,
1615 server->id, SILC_ID_SERVER,
1616 chl->client->id, NULL);
1618 idp1 = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1619 idp2 = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
1620 SILC_PUT32_MSB(forced_mode, cumode);
1621 silc_server_send_notify_to_channel(server, sock, channel, FALSE,
1622 SILC_NOTIFY_TYPE_CUMODE_CHANGE,
1623 3, idp1->data, idp1->len,
1624 cumode, sizeof(cumode),
1625 idp2->data, idp2->len);
1626 silc_buffer_free(idp1);
1627 silc_buffer_free(idp2);
1632 /* Find active socket connection by the IP address and port indicated by
1633 `ip' and `port', and socket connection type of `type'. */
1635 SilcSocketConnection
1636 silc_server_find_socket_by_host(SilcServer server,
1637 SilcSocketType type,
1638 const char *ip, SilcUInt16 port)
1642 for (i = 0; i < server->config->param.connections_max; i++) {
1643 if (!server->sockets[i])
1645 if (!strcmp(server->sockets[i]->ip, ip) &&
1646 (!port || server->sockets[i]->port == port) &&
1647 server->sockets[i]->type == type)
1648 return server->sockets[i];