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;
45 SILC_LOG_DEBUG(("Remove client from all channels"));
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_SERVER &&
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_SERVER &&
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 removes all client entries that are originated from
123 `router' and are owned by `entry'. `router' and `entry' can be same
124 too. If `server_signoff' is TRUE then SERVER_SIGNOFF notify is
125 distributed to our local clients. */
127 bool silc_server_remove_clients_by_server(SilcServer server,
128 SilcServerEntry router,
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(("Removing clients by %s",
147 entry->server_name ? entry->server_name : "server"));
152 /* Allocate the hash table that holds the channels that require
153 channel key re-generation after we've removed this server's clients
154 from the channels. */
155 channels = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL,
157 clients = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL,
160 if (server_signoff) {
161 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
162 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
163 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) * (argc + 1));
164 argv_types = silc_realloc(argv_types, sizeof(*argv_types) * (argc + 1));
165 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
166 memcpy(argv[argc], idp->data, idp->len);
167 argv_lens[argc] = idp->len;
168 argv_types[argc] = argc + 1;
170 silc_buffer_free(idp);
173 if (silc_idcache_get_all(server->local_list->clients, &list)) {
174 if (silc_idcache_list_first(list, &id_cache)) {
176 client = (SilcClientEntry)id_cache->context;
178 /* If client is not registered, is not originated from `router'
179 or is not owned by `entry', skip it. */
180 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
181 client->router != router ||
182 (router != entry && !SILC_ID_COMPARE(client->id, entry->id,
183 client->id->ip.data_len))) {
184 if (!silc_idcache_list_next(list, &id_cache))
190 if (server_signoff) {
191 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
192 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
193 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
195 argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
197 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
198 memcpy(argv[argc], idp->data, idp->len);
199 argv_lens[argc] = idp->len;
200 argv_types[argc] = argc + 1;
202 silc_buffer_free(idp);
205 /* Update statistics */
206 server->stat.clients--;
207 if (server->stat.cell_clients)
208 server->stat.cell_clients--;
209 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
210 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
212 silc_server_remove_clients_channels(server, entry, clients,
214 silc_server_del_from_watcher_list(server, client);
216 /* Remove the client entry */
217 if (!server_signoff) {
218 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
219 id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
221 silc_idlist_del_client(server->local_list, client);
224 if (!silc_idcache_list_next(list, &id_cache))
228 silc_idcache_list_free(list);
231 if (silc_idcache_get_all(server->global_list->clients, &list)) {
233 if (silc_idcache_list_first(list, &id_cache)) {
235 client = (SilcClientEntry)id_cache->context;
237 /* If client is not registered, is not originated from `router'
238 or is not owned by `entry', skip it. */
239 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
240 client->router != router ||
241 (router != entry && !SILC_ID_COMPARE(client->id, entry->id,
242 client->id->ip.data_len))) {
243 if (!silc_idcache_list_next(list, &id_cache))
249 if (server_signoff) {
250 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
251 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
252 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
254 argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
256 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
257 memcpy(argv[argc], idp->data, idp->len);
258 argv_lens[argc] = idp->len;
259 argv_types[argc] = argc + 1;
261 silc_buffer_free(idp);
264 /* Update statistics */
265 server->stat.clients--;
266 if (server->stat.cell_clients)
267 server->stat.cell_clients--;
268 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
269 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
271 silc_server_remove_clients_channels(server, entry, clients,
273 silc_server_del_from_watcher_list(server, client);
275 /* Remove the client entry */
276 if (!server_signoff) {
277 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
278 id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
280 silc_idlist_del_client(server->global_list, client);
283 if (!silc_idcache_list_next(list, &id_cache))
287 silc_idcache_list_free(list);
290 /* Send the SERVER_SIGNOFF notify */
291 if (server_signoff) {
292 SilcBuffer args, not;
294 SILC_LOG_DEBUG(("Sending SERVER_SIGNOFF for %s with %d clients",
295 silc_id_render(entry->id, SILC_ID_SERVER), argc - 1));
297 /* Send SERVER_SIGNOFF notify to our primary router */
298 if (server->router != entry) {
299 args = silc_argument_payload_encode(1, argv, argv_lens,
301 silc_server_send_notify_args(server, SILC_PRIMARY_ROUTE(server),
302 SILC_BROADCAST(server),
303 SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
305 silc_buffer_free(args);
308 /* Send to local clients. We also send the list of client ID's that
309 is to be removed for those servers that would like to use that list. */
310 args = silc_argument_payload_encode(argc, argv, argv_lens,
312 not = silc_notify_payload_encode_args(SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
314 silc_server_packet_send_clients(server, clients,
315 SILC_PACKET_NOTIFY, 0, FALSE,
316 not->data, not->len, FALSE);
318 silc_buffer_free(args);
319 silc_buffer_free(not);
320 for (i = 0; i < argc; i++)
323 silc_free(argv_lens);
324 silc_free(argv_types);
325 silc_hash_table_free(clients);
328 /* Return now if we are shutting down */
329 if (server->server_shutdown) {
330 silc_hash_table_free(channels);
334 /* We must now re-generate the channel key for all channels that had
335 this server's client(s) on the channel. As they left the channel we
336 must re-generate the channel key. */
337 silc_hash_table_list(channels, &htl);
338 while (silc_hash_table_get(&htl, NULL, (void **)&channel)) {
339 if (!silc_server_create_channel_key(server, channel, 0)) {
340 silc_hash_table_list_reset(&htl);
341 silc_hash_table_free(channels);
345 /* Do not send the channel key if private channel key mode is set */
346 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY)
349 silc_server_send_channel_key(server, NULL, channel,
350 server->server_type == SILC_ROUTER ?
351 FALSE : !server->standalone);
353 silc_hash_table_list_reset(&htl);
354 silc_hash_table_free(channels);
359 static SilcServerEntry
360 silc_server_update_clients_by_real_server(SilcServer server,
361 SilcServerEntry from,
362 SilcClientEntry client,
364 SilcIDCacheEntry client_cache)
366 SilcServerEntry server_entry;
367 SilcIDCacheEntry id_cache = NULL;
368 SilcIDCacheList list;
370 if (!silc_idcache_get_all(server->local_list->servers, &list))
373 if (silc_idcache_list_first(list, &id_cache)) {
375 server_entry = (SilcServerEntry)id_cache->context;
376 if (server_entry != from &&
377 SILC_ID_COMPARE(server_entry->id, client->id,
378 client->id->ip.data_len)) {
379 SILC_LOG_DEBUG(("Found (local) %s",
380 silc_id_render(server_entry->id, SILC_ID_SERVER)));
382 if (!server_entry->data.send_key && server_entry->router) {
383 SILC_LOG_DEBUG(("Server not locally connected, use its router"));
384 /* If the client is not marked as local then move it to local list
385 since the server is local. */
387 SILC_LOG_DEBUG(("Moving client to local list"));
388 silc_idcache_add(server->local_list->clients, client_cache->name,
389 client_cache->id, client_cache->context,
390 client_cache->expire, NULL);
391 silc_idcache_del_by_context(server->global_list->clients, client);
393 server_entry = server_entry->router;
395 /* If the client is not marked as local then move it to local list
396 since the server is local. */
397 if (server_entry->server_type != SILC_BACKUP_ROUTER && !local) {
398 SILC_LOG_DEBUG(("Moving client to local list"));
399 silc_idcache_add(server->local_list->clients, client_cache->name,
400 client_cache->id, client_cache->context,
401 client_cache->expire, NULL);
402 silc_idcache_del_by_context(server->global_list->clients, client);
406 silc_idcache_list_free(list);
410 if (!silc_idcache_list_next(list, &id_cache))
415 silc_idcache_list_free(list);
417 if (!silc_idcache_get_all(server->global_list->servers, &list))
420 if (silc_idcache_list_first(list, &id_cache)) {
422 server_entry = (SilcServerEntry)id_cache->context;
423 if (server_entry != from &&
424 SILC_ID_COMPARE(server_entry->id, client->id,
425 client->id->ip.data_len)) {
426 SILC_LOG_DEBUG(("Found (global) %s",
427 silc_id_render(server_entry->id, SILC_ID_SERVER)));
429 if (!server_entry->data.send_key && server_entry->router) {
430 SILC_LOG_DEBUG(("Server not locally connected, use its router"));
431 /* If the client is marked as local then move it to global list
432 since the server is global. */
434 SILC_LOG_DEBUG(("Moving client to global list"));
435 silc_idcache_add(server->global_list->clients, client_cache->name,
436 client_cache->id, client_cache->context,
437 client_cache->expire, NULL);
438 silc_idcache_del_by_context(server->local_list->clients, client);
440 server_entry = server_entry->router;
442 /* If the client is marked as local then move it to global list
443 since the server is global. */
444 if (server_entry->server_type != SILC_BACKUP_ROUTER && local) {
445 SILC_LOG_DEBUG(("Moving client to global list"));
446 silc_idcache_add(server->global_list->clients, client_cache->name,
447 client_cache->id, client_cache->context,
448 client_cache->expire, NULL);
449 silc_idcache_del_by_context(server->local_list->clients, client);
453 silc_idcache_list_free(list);
457 if (!silc_idcache_list_next(list, &id_cache))
462 silc_idcache_list_free(list);
467 /* Updates the clients that are originated from the `from' to be originated
468 from the `to'. If the `resolve_real_server' is TRUE then this will
469 attempt to figure out which clients really are originated from the
470 `from' and which are originated from a server that we have connection
471 to, when we've acting as backup router. If it is FALSE the `to' will
472 be the new source. */
474 void silc_server_update_clients_by_server(SilcServer server,
475 SilcServerEntry from,
477 bool resolve_real_server)
479 SilcIDCacheList list = NULL;
480 SilcIDCacheEntry id_cache = NULL;
481 SilcClientEntry client = NULL;
485 if (silc_idcache_get_all(server->global_list->clients, &list)) {
486 if (silc_idcache_list_first(list, &id_cache)) {
488 client = (SilcClientEntry)id_cache->context;
490 /* If entry is disabled skip it. If entry is local to us, do not
491 switch it to anyone else, it is ours so skip it. */
492 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
493 SILC_IS_LOCAL(client)) {
494 if (!silc_idcache_list_next(list, &id_cache))
500 SILC_LOG_DEBUG(("Client %s",
501 silc_id_render(client->id, SILC_ID_CLIENT)));
503 SILC_LOG_DEBUG(("Client->router %s",
504 silc_id_render(client->router->id, SILC_ID_SERVER)));
507 if (client->router == from) {
508 if (resolve_real_server) {
510 silc_server_update_clients_by_real_server(server, from, client,
512 if (!client->router) {
513 if (server->server_type == SILC_ROUTER)
514 client->router = from;
523 /* All are changed */
528 SILC_LOG_DEBUG(("Client changed to %s",
529 silc_id_render(client->router->id, SILC_ID_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 %s",
555 silc_id_render(client->id, SILC_ID_CLIENT)));
557 SILC_LOG_DEBUG(("Client->router %s",
558 silc_id_render(client->router->id, SILC_ID_SERVER)));
561 if (client->router == from) {
562 if (resolve_real_server) {
564 silc_server_update_clients_by_real_server(server, from, client,
567 client->router = from;
573 /* All are changed */
578 SILC_LOG_DEBUG(("Client changed to %s",
579 silc_id_render(client->router->id, SILC_ID_CLIENT)));
581 if (!silc_idcache_list_next(list, &id_cache))
585 silc_idcache_list_free(list);
589 /* Updates servers that are from `from' to be originated from `to'. This
590 will also update the server's connection to `to's connection. */
592 void silc_server_update_servers_by_server(SilcServer server,
593 SilcServerEntry from,
596 SilcIDCacheList list = NULL;
597 SilcIDCacheEntry id_cache = NULL;
598 SilcServerEntry server_entry = NULL;
600 SILC_LOG_DEBUG(("Updating servers"));
602 if (silc_idcache_get_all(server->local_list->servers, &list)) {
603 if (silc_idcache_list_first(list, &id_cache)) {
605 server_entry = (SilcServerEntry)id_cache->context;
607 /* If entry is local to us, do not switch it to any anyone else,
609 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
610 server_entry == from) {
611 if (!silc_idcache_list_next(list, &id_cache))
617 /* If we are standalone router, any server that is not directly
618 connected to cannot exist anymore. If we are not standalone
619 we update it correctly. */
620 if (server->server_type == SILC_ROUTER && server->standalone) {
621 silc_server_backup_del(server, server_entry);
622 silc_server_backup_replaced_del(server, server_entry);
623 silc_idlist_del_data(server_entry);
624 silc_idlist_del_server(server->local_list, server_entry);
625 server->stat.servers--;
626 server->stat.cell_servers--;
628 /* XXX if we are not standalone, do a check from local config
629 whether this server is in our cell, but not connected to
630 us (in which case we must remove it). */
632 if (server_entry->router == from) {
633 SILC_LOG_DEBUG(("Updating server (local) %s",
634 server_entry->server_name ?
635 server_entry->server_name : ""));
636 server_entry->router = to;
637 server_entry->connection = to->connection;
641 if (!silc_idcache_list_next(list, &id_cache))
645 silc_idcache_list_free(list);
648 if (silc_idcache_get_all(server->global_list->servers, &list)) {
649 if (silc_idcache_list_first(list, &id_cache)) {
651 server_entry = (SilcServerEntry)id_cache->context;
653 /* If entry is local to us, do not switch it to anyone else,
655 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
656 server_entry == from) {
657 if (!silc_idcache_list_next(list, &id_cache))
663 /* If we are standalone router, any server that is not directly
664 connected to cannot exist anymore. If we are not standalone
665 we update it correctly. */
666 if (server->server_type == SILC_ROUTER && server->standalone) {
667 silc_server_backup_del(server, server_entry);
668 silc_server_backup_replaced_del(server, server_entry);
669 silc_idlist_del_data(server_entry);
670 silc_idlist_del_server(server->global_list, server_entry);
671 server->stat.servers--;
672 server->stat.cell_servers--;
674 /* XXX if we are not standalone, do a check from local config
675 whether this server is in our cell, but not connected to
676 us (in which case we must remove it). */
678 if (server_entry->router == from) {
679 SILC_LOG_DEBUG(("Updating server (global) %s",
680 server_entry->server_name ?
681 server_entry->server_name : ""));
682 server_entry->router = to;
683 server_entry->connection = to->connection;
687 if (!silc_idcache_list_next(list, &id_cache))
691 silc_idcache_list_free(list);
696 /* Toggles the enabled/disabled status of local server connections. Packets
697 can be sent to the servers when `toggle_enabled' is TRUE and will be
698 dropped if `toggle_enabled' is FALSE, after this function is called. */
700 void silc_server_local_servers_toggle_enabled(SilcServer server,
703 SilcIDCacheList list = NULL;
704 SilcIDCacheEntry id_cache = NULL;
705 SilcServerEntry server_entry = NULL;
707 if (silc_idcache_get_all(server->local_list->servers, &list)) {
708 if (silc_idcache_list_first(list, &id_cache)) {
710 server_entry = (SilcServerEntry)id_cache->context;
711 if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry) {
712 if (!silc_idcache_list_next(list, &id_cache))
719 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
721 server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
723 if (!silc_idcache_list_next(list, &id_cache))
727 silc_idcache_list_free(list);
730 if (silc_idcache_get_all(server->global_list->servers, &list)) {
731 if (silc_idcache_list_first(list, &id_cache)) {
733 server_entry = (SilcServerEntry)id_cache->context;
734 if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry) {
735 if (!silc_idcache_list_next(list, &id_cache))
742 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
744 server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
746 if (!silc_idcache_list_next(list, &id_cache))
750 silc_idcache_list_free(list);
754 /* Removes servers that are originated from the `from'. The server
755 entry is deleted in this function. If `remove_clients' is TRUE then
756 all clients originated from the server are removed too, and server
757 signoff is sent. Note that this does not remove the `from'. This
758 also does not remove locally connected servers. */
760 void silc_server_remove_servers_by_server(SilcServer server,
761 SilcServerEntry from,
764 SilcIDCacheList list = NULL;
765 SilcIDCacheEntry id_cache = NULL;
766 SilcServerEntry server_entry = NULL;
768 SILC_LOG_DEBUG(("Removing servers by %s",
769 from->server_name ? from->server_name : "server"));
771 if (silc_idcache_get_all(server->local_list->servers, &list)) {
772 if (silc_idcache_list_first(list, &id_cache)) {
774 server_entry = (SilcServerEntry)id_cache->context;
775 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
776 server_entry->router != from || server_entry == from) {
777 if (!silc_idcache_list_next(list, &id_cache))
783 /* Remove clients owned by this server */
785 silc_server_remove_clients_by_server(server, from, server_entry,
788 /* Remove the server */
789 silc_idlist_del_server(server->local_list, server_entry);
791 if (!silc_idcache_list_next(list, &id_cache))
795 silc_idcache_list_free(list);
798 if (silc_idcache_get_all(server->global_list->servers, &list)) {
799 if (silc_idcache_list_first(list, &id_cache)) {
801 server_entry = (SilcServerEntry)id_cache->context;
802 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
803 server_entry->router != from || server_entry == from) {
804 if (!silc_idcache_list_next(list, &id_cache))
810 /* Remove clients owned by this server */
812 silc_server_remove_clients_by_server(server, from, server_entry,
815 /* Remove the server */
816 silc_idlist_del_server(server->global_list, server_entry);
818 if (!silc_idcache_list_next(list, &id_cache))
822 silc_idcache_list_free(list);
826 /* Removes channels that are from `from. */
828 void silc_server_remove_channels_by_server(SilcServer server,
829 SilcServerEntry from)
831 SilcIDCacheList list = NULL;
832 SilcIDCacheEntry id_cache = NULL;
833 SilcChannelEntry channel = NULL;
835 SILC_LOG_DEBUG(("Removing channels by server"));
837 if (silc_idcache_get_all(server->global_list->channels, &list)) {
838 if (silc_idcache_list_first(list, &id_cache)) {
840 channel = (SilcChannelEntry)id_cache->context;
841 if (channel->router == from)
842 silc_idlist_del_channel(server->global_list, channel);
843 if (!silc_idcache_list_next(list, &id_cache))
847 silc_idcache_list_free(list);
851 /* Updates channels that are from `from' to be originated from `to'. */
853 void silc_server_update_channels_by_server(SilcServer server,
854 SilcServerEntry from,
857 SilcIDCacheList list = NULL;
858 SilcIDCacheEntry id_cache = NULL;
859 SilcChannelEntry channel = NULL;
861 SILC_LOG_DEBUG(("Updating channels by server"));
863 if (silc_idcache_get_all(server->global_list->channels, &list)) {
864 if (silc_idcache_list_first(list, &id_cache)) {
866 channel = (SilcChannelEntry)id_cache->context;
867 if (channel->router == from)
868 channel->router = to;
869 if (!silc_idcache_list_next(list, &id_cache))
873 silc_idcache_list_free(list);
877 /* Checks whether given channel has global users. If it does this returns
878 TRUE and FALSE if there is only locally connected clients on the channel. */
880 bool silc_server_channel_has_global(SilcChannelEntry channel)
882 SilcChannelClientEntry chl;
883 SilcHashTableList htl;
885 silc_hash_table_list(channel->user_list, &htl);
886 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
887 if (chl->client->router) {
888 silc_hash_table_list_reset(&htl);
892 silc_hash_table_list_reset(&htl);
897 /* Checks whether given channel has locally connected users. If it does this
898 returns TRUE and FALSE if there is not one locally connected client. */
900 bool silc_server_channel_has_local(SilcChannelEntry channel)
902 SilcChannelClientEntry chl;
903 SilcHashTableList htl;
905 silc_hash_table_list(channel->user_list, &htl);
906 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
907 if (!chl->client->router) {
908 silc_hash_table_list_reset(&htl);
912 silc_hash_table_list_reset(&htl);
917 /* This function removes the channel and all users on the channel, unless
918 the channel is permanent. In this case the channel is disabled but all
919 users are removed from the channel. Returns TRUE if the channel is
920 destroyed totally, and FALSE if it is permanent and remains. */
922 bool silc_server_channel_delete(SilcServer server,
923 SilcChannelEntry channel)
925 SilcChannelClientEntry chl;
926 SilcHashTableList htl;
927 bool delchan = !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH);
930 /* Update statistics */
931 if (server->server_type == SILC_ROUTER)
932 server->stat.chanclients -= channel->user_count;
934 /* Totally delete the channel and all users on the channel. The
935 users are deleted automatically in silc_idlist_del_channel. */
936 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
937 if (silc_idlist_del_channel(server->local_list, channel)) {
938 server->stat.my_channels--;
939 if (server->server_type == SILC_ROUTER) {
940 server->stat.channels--;
941 server->stat.cell_channels--;
944 if (silc_idlist_del_channel(server->global_list, channel))
945 if (server->server_type == SILC_ROUTER)
946 server->stat.channels--;
952 /* Channel is permanent, do not remove it, remove only users */
953 channel->disabled = TRUE;
954 silc_hash_table_list(channel->user_list, &htl);
955 while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
956 silc_hash_table_del(chl->client->channels, channel);
957 silc_hash_table_del(channel->user_list, chl->client);
958 channel->user_count--;
960 /* Update statistics */
961 if (SILC_IS_LOCAL(chl->client))
962 server->stat.my_chanclients--;
963 if (server->server_type == SILC_ROUTER) {
964 server->stat.cell_chanclients--;
965 server->stat.chanclients--;
970 silc_hash_table_list_reset(&htl);
972 SILC_LOG_DEBUG(("Channel %s remains", channel->channel_name));
977 /* Returns TRUE if the given client is on the channel. FALSE if not.
978 This works because we assure that the user list on the channel is
979 always in up to date thus we can only check the channel list from
980 `client' which is faster than checking the user list from `channel'. */
982 bool silc_server_client_on_channel(SilcClientEntry client,
983 SilcChannelEntry channel,
984 SilcChannelClientEntry *chl)
986 if (!client || !channel)
989 return silc_hash_table_find(client->channels, channel, NULL,
993 /* Checks string for bad characters and returns TRUE if they are found. */
995 bool silc_server_name_bad_chars(const char *name, SilcUInt32 name_len)
999 for (i = 0; i < name_len; i++) {
1000 if (!isascii(name[i]))
1002 if (name[i] <= 32) return TRUE;
1003 if (name[i] == ' ') return TRUE;
1004 if (name[i] == '*') return TRUE;
1005 if (name[i] == '?') return TRUE;
1006 if (name[i] == ',') return TRUE;
1012 /* Modifies the `name' if it includes bad characters and returns new
1013 allocated name that does not include bad characters. */
1015 char *silc_server_name_modify_bad(const char *name, SilcUInt32 name_len)
1018 char *newname = strdup(name);
1020 for (i = 0; i < name_len; i++) {
1021 if (!isascii(newname[i])) newname[i] = '_';
1022 if (newname[i] <= 32) newname[i] = '_';
1023 if (newname[i] == ' ') newname[i] = '_';
1024 if (newname[i] == '*') newname[i] = '_';
1025 if (newname[i] == '?') newname[i] = '_';
1026 if (newname[i] == ',') newname[i] = '_';
1032 /* Find number of sockets by IP address indicated by `ip'. Returns 0 if
1033 socket connections with the IP address does not exist. */
1035 SilcUInt32 silc_server_num_sockets_by_ip(SilcServer server, const char *ip,
1036 SilcSocketType type)
1040 for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
1041 if (server->sockets[i] && !SILC_IS_LISTENER(server->sockets[i]) &&
1042 !strcmp(server->sockets[i]->ip, ip) &&
1043 server->sockets[i]->type == type)
1050 /* Find number of sockets by IP address indicated by remote host, indicatd
1051 by `ip' or `hostname', `port', and `type'. Returns 0 if socket connections
1052 does not exist. If `ip' is provided then `hostname' is ignored. */
1054 SilcUInt32 silc_server_num_sockets_by_remote(SilcServer server,
1056 const char *hostname,
1058 SilcSocketType type)
1062 if (!ip && !hostname)
1065 for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
1066 if (server->sockets[i] && !SILC_IS_LISTENER(server->sockets[i]) &&
1067 ((ip && !strcmp(server->sockets[i]->ip, ip)) ||
1068 (hostname && !strcmp(server->sockets[i]->hostname, hostname))) &&
1069 server->sockets[i]->port == port &&
1070 server->sockets[i]->type == type)
1077 /* Finds locally cached public key by the public key received in the SKE.
1078 If we have it locally cached then we trust it and will use it in the
1079 authentication protocol. Returns the locally cached public key or NULL
1080 if we do not find the public key. */
1082 SilcPublicKey silc_server_find_public_key(SilcServer server,
1083 SilcHashTable local_public_keys,
1084 SilcPublicKey remote_public_key)
1086 SilcPublicKey cached_key;
1088 SILC_LOG_DEBUG(("Find remote public key (%d keys in local cache)",
1089 silc_hash_table_count(local_public_keys)));
1091 if (!silc_hash_table_find_ext(local_public_keys, remote_public_key,
1092 (void **)&cached_key, NULL,
1093 silc_hash_public_key, NULL,
1094 silc_hash_public_key_compare, NULL)) {
1095 SILC_LOG_ERROR(("Public key not found"));
1099 SILC_LOG_DEBUG(("Found public key"));
1104 /* This returns the first public key from the table of public keys. This
1105 is used only in cases where single public key exists in the table and
1106 we want to get a pointer to it. For public key tables that has multiple
1107 keys in it the silc_server_find_public_key must be used. */
1109 SilcPublicKey silc_server_get_public_key(SilcServer server,
1110 SilcHashTable local_public_keys)
1112 SilcPublicKey cached_key;
1113 SilcHashTableList htl;
1115 SILC_LOG_DEBUG(("Start"));
1117 assert(silc_hash_table_count(local_public_keys) < 2);
1119 silc_hash_table_list(local_public_keys, &htl);
1120 if (!silc_hash_table_get(&htl, NULL, (void **)&cached_key))
1122 silc_hash_table_list_reset(&htl);
1127 /* Check whether the connection `sock' is allowed to connect to us. This
1128 checks for example whether there is too much connections for this host,
1129 and required version for the host etc. */
1131 bool silc_server_connection_allowed(SilcServer server,
1132 SilcSocketConnection sock,
1133 SilcSocketType type,
1134 SilcServerConfigConnParams *global,
1135 SilcServerConfigConnParams *params,
1138 SilcUInt32 conn_number = (type == SILC_SOCKET_TYPE_CLIENT ?
1139 server->stat.my_clients :
1140 type == SILC_SOCKET_TYPE_SERVER ?
1141 server->stat.my_servers :
1142 server->stat.my_routers);
1143 SilcUInt32 num_sockets, max_hosts, max_per_host;
1144 SilcUInt32 r_protocol_version, l_protocol_version;
1145 SilcUInt32 r_software_version, l_software_version;
1146 char *r_vendor_version = NULL, *l_vendor_version;
1148 SILC_LOG_DEBUG(("Checking whether connection is allowed"));
1152 l_protocol_version =
1153 silc_version_to_num(params && params->version_protocol ?
1154 params->version_protocol :
1155 global->version_protocol);
1156 l_software_version =
1157 silc_version_to_num(params && params->version_software ?
1158 params->version_software :
1159 global->version_software);
1160 l_vendor_version = (params && params->version_software_vendor ?
1161 params->version_software_vendor :
1162 global->version_software_vendor);
1164 if (ske && silc_ske_parse_version(ske, &r_protocol_version, NULL,
1165 &r_software_version, NULL,
1166 &r_vendor_version)) {
1167 sock->version = r_protocol_version;
1169 /* Match protocol version */
1170 if (l_protocol_version && r_protocol_version &&
1171 r_protocol_version < l_protocol_version) {
1172 SILC_LOG_INFO(("Connection %s (%s) is too old version",
1173 sock->hostname, sock->ip));
1174 silc_server_disconnect_remote(server, sock,
1175 SILC_STATUS_ERR_BAD_VERSION,
1176 "You support too old protocol version");
1180 /* Math software version */
1181 if (l_software_version && r_software_version &&
1182 r_software_version < l_software_version) {
1183 SILC_LOG_INFO(("Connection %s (%s) is too old version",
1184 sock->hostname, sock->ip));
1185 silc_server_disconnect_remote(server, sock,
1186 SILC_STATUS_ERR_BAD_VERSION,
1187 "You support too old software version");
1191 /* Regex match vendor version */
1192 if (l_vendor_version && r_vendor_version &&
1193 !silc_string_match(l_vendor_version, r_vendor_version)) {
1194 SILC_LOG_INFO(("Connection %s (%s) is unsupported version",
1195 sock->hostname, sock->ip));
1196 silc_server_disconnect_remote(server, sock,
1197 SILC_STATUS_ERR_BAD_VERSION,
1198 "Your software is not supported");
1202 silc_free(r_vendor_version);
1204 /* Check for maximum connections limit */
1206 num_sockets = silc_server_num_sockets_by_ip(server, sock->ip, type);
1207 max_hosts = (params ? params->connections_max : global->connections_max);
1208 max_per_host = (params ? params->connections_max_per_host :
1209 global->connections_max_per_host);
1211 if (max_hosts && conn_number >= max_hosts) {
1212 SILC_LOG_INFO(("Server is full, closing %s (%s) connection",
1213 sock->hostname, sock->ip));
1214 silc_server_disconnect_remote(server, sock,
1215 SILC_STATUS_ERR_RESOURCE_LIMIT,
1216 "Server is full, try again later");
1220 if (num_sockets >= max_per_host) {
1221 SILC_LOG_INFO(("Too many connections from %s (%s), closing connection",
1222 sock->hostname, sock->ip));
1223 silc_server_disconnect_remote(server, sock,
1224 SILC_STATUS_ERR_RESOURCE_LIMIT,
1225 "Too many connections from your host");
1232 /* Checks that client has rights to add or remove channel modes. If any
1233 of the checks fails FALSE is returned. */
1235 bool silc_server_check_cmode_rights(SilcServer server,
1236 SilcChannelEntry channel,
1237 SilcChannelClientEntry client,
1240 bool is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1241 bool is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1243 /* Check whether has rights to change anything */
1244 if (!is_op && !is_fo)
1247 /* Check whether has rights to change everything */
1251 /* Founder implies operator */
1255 /* We know that client is channel operator, check that they are not
1256 changing anything that requires channel founder rights. Rest of the
1257 modes are available automatically for channel operator. */
1259 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1260 if (is_op && !is_fo)
1263 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1264 if (is_op && !is_fo)
1269 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1270 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
1271 if (is_op && !is_fo)
1275 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1276 if (is_op && !is_fo)
1281 if (mode & SILC_CHANNEL_MODE_CIPHER) {
1282 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
1283 if (is_op && !is_fo)
1287 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1288 if (is_op && !is_fo)
1293 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1294 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
1295 if (is_op && !is_fo)
1299 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1300 if (is_op && !is_fo)
1305 if (mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1306 if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS)) {
1307 if (is_op && !is_fo)
1311 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1312 if (is_op && !is_fo)
1317 if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1318 if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS)) {
1319 if (is_op && !is_fo)
1323 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1324 if (is_op && !is_fo)
1332 /* Check that the client has rights to change its user mode. Returns
1333 FALSE if setting some mode is not allowed. */
1335 bool silc_server_check_umode_rights(SilcServer server,
1336 SilcClientEntry client,
1339 bool server_op = FALSE, router_op = FALSE;
1341 if (mode & SILC_UMODE_SERVER_OPERATOR) {
1342 /* Cannot set server operator mode (must use OPER command) */
1343 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR))
1346 /* Remove the server operator rights */
1347 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
1351 if (mode & SILC_UMODE_ROUTER_OPERATOR) {
1352 /* Cannot set router operator mode (must use SILCOPER command) */
1353 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR))
1356 /* Remove the router operator rights */
1357 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
1362 SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR);
1364 SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR);
1369 /* This function is used to send the notify packets and motd to the
1370 incoming client connection. */
1372 void silc_server_send_connect_notifys(SilcServer server,
1373 SilcSocketConnection sock,
1374 SilcClientEntry client)
1376 SilcIDListData idata = (SilcIDListData)client;
1378 SILC_LOG_DEBUG(("Send welcome notifys"));
1380 /* Send some nice info to the client */
1381 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1382 ("Welcome to the SILC Network %s",
1384 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1385 ("Your host is %s, running version %s",
1386 server->server_name, server_version));
1388 if (server->server_type == SILC_ROUTER) {
1389 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1390 ("There are %d clients, %d servers and %d "
1391 "routers in SILC Network",
1392 server->stat.clients, server->stat.servers + 1,
1393 server->stat.routers));
1395 if (server->stat.clients && server->stat.servers + 1)
1396 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1397 ("There are %d clients, %d servers and %d "
1398 "routers in SILC Network",
1399 server->stat.clients, server->stat.servers + 1,
1400 (server->standalone ? 0 :
1401 !server->stat.routers ? 1 :
1402 server->stat.routers)));
1405 if (server->stat.cell_clients && server->stat.cell_servers + 1)
1406 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1407 ("There are %d clients on %d server in our cell",
1408 server->stat.cell_clients,
1409 server->stat.cell_servers + 1));
1410 if (server->server_type == SILC_ROUTER) {
1411 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1412 ("I have %d clients, %d channels, %d servers and "
1414 server->stat.my_clients,
1415 server->stat.my_channels,
1416 server->stat.my_servers,
1417 server->stat.my_routers));
1419 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1420 ("I have %d clients and %d channels formed",
1421 server->stat.my_clients,
1422 server->stat.my_channels));
1425 if (server->stat.server_ops || server->stat.router_ops)
1426 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1427 ("There are %d server operators and %d router "
1429 server->stat.server_ops,
1430 server->stat.router_ops));
1431 if (server->stat.my_router_ops + server->stat.my_server_ops)
1432 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1433 ("I have %d operators online",
1434 server->stat.my_router_ops +
1435 server->stat.my_server_ops));
1437 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1438 ("Your connection is secured with %s cipher, "
1439 "key length %d bits",
1440 idata->send_key->cipher->name,
1441 idata->send_key->cipher->key_len));
1442 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1443 ("Your current nickname is %s",
1447 silc_server_send_motd(server, sock);
1450 /* Kill the client indicated by `remote_client' sending KILLED notify
1451 to the client, to all channels client has joined and to primary
1452 router if needed. The killed client is also removed from all channels. */
1454 void silc_server_kill_client(SilcServer server,
1455 SilcClientEntry remote_client,
1456 const char *comment,
1458 SilcIdType killer_id_type)
1460 SilcBuffer killed, killer;
1462 SILC_LOG_DEBUG(("Killing client %s",
1463 silc_id_render(remote_client->id, SILC_ID_CLIENT)));
1465 /* Send the KILL notify packets. First send it to the channel, then
1466 to our primary router and then directly to the client who is being
1467 killed right now. */
1469 killed = silc_id_payload_encode(remote_client->id, SILC_ID_CLIENT);
1470 killer = silc_id_payload_encode(killer_id, killer_id_type);
1472 /* Send KILLED notify to the channels. It is not sent to the client
1473 as it will be sent differently destined directly to the client and not
1475 silc_server_send_notify_on_channels(server, remote_client,
1476 remote_client, SILC_NOTIFY_TYPE_KILLED,
1477 3, killed->data, killed->len,
1478 comment, comment ? strlen(comment) : 0,
1479 killer->data, killer->len);
1481 /* Send KILLED notify to primary route */
1482 silc_server_send_notify_killed(server, SILC_PRIMARY_ROUTE(server),
1483 SILC_BROADCAST(server), remote_client->id,
1484 comment, killer_id, killer_id_type);
1486 /* Send KILLED notify to the client directly */
1487 if (remote_client->connection || remote_client->router)
1488 silc_server_send_notify_killed(server, remote_client->connection ?
1489 remote_client->connection :
1490 remote_client->router->connection, FALSE,
1491 remote_client->id, comment,
1492 killer_id, killer_id_type);
1494 /* Remove the client from all channels. This generates new keys to the
1495 channels as well. */
1496 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
1499 /* Remove the client entry, If it is locally connected then we will also
1500 disconnect the client here */
1501 if (remote_client->connection) {
1502 /* Remove locally conneted client */
1503 SilcSocketConnection sock = remote_client->connection;
1504 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
1505 silc_server_close_connection(server, sock);
1507 /* Update statistics */
1508 server->stat.clients--;
1509 if (server->stat.cell_clients)
1510 server->stat.cell_clients--;
1511 SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
1512 SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
1514 if (SILC_IS_LOCAL(remote_client)) {
1515 server->stat.my_clients--;
1516 silc_schedule_task_del_by_context(server->schedule, remote_client);
1517 silc_idlist_del_data(remote_client);
1520 /* Remove remote client */
1521 if (!silc_idlist_del_client(server->global_list, remote_client)) {
1522 /* Remove this client from watcher list if it is */
1523 silc_server_del_from_watcher_list(server, remote_client);
1524 silc_idlist_del_client(server->local_list, remote_client);
1528 silc_buffer_free(killer);
1529 silc_buffer_free(killed);
1534 SilcClientEntry client;
1535 SilcNotifyType notify;
1536 const char *new_nick;
1537 } WatcherNotifyContext;
1540 silc_server_check_watcher_list_foreach(void *key, void *context,
1543 WatcherNotifyContext *notify = user_context;
1544 SilcClientEntry entry = context;
1545 SilcSocketConnection sock;
1547 if (entry == notify->client)
1550 sock = silc_server_get_client_route(notify->server, NULL, 0, entry->id,
1553 SILC_LOG_DEBUG(("Sending WATCH notify to %s",
1554 silc_id_render(entry->id, SILC_ID_CLIENT)));
1556 /* Send the WATCH notify */
1557 silc_server_send_notify_watch(notify->server, sock, entry,
1559 notify->new_nick ? notify->new_nick :
1560 (const char *)notify->client->nickname,
1565 /* This function checks whether the `client' nickname is being watched
1566 by someone, and notifies the watcher of the notify change of notify
1567 type indicated by `notify'. */
1569 bool silc_server_check_watcher_list(SilcServer server,
1570 SilcClientEntry client,
1571 const char *new_nick,
1572 SilcNotifyType notify)
1574 unsigned char hash[16];
1575 WatcherNotifyContext n;
1577 SILC_LOG_DEBUG(("Checking watcher list %s",
1578 client->nickname ? client->nickname : (unsigned char *)""));
1580 /* If the watching is rejected by the client do nothing */
1581 if (client->mode & SILC_UMODE_REJECT_WATCHING)
1584 /* Make hash from the nick, or take it from Client ID */
1585 if (client->nickname) {
1587 memset(nick, 0, sizeof(nick));
1588 silc_to_lower(client->nickname, nick, sizeof(nick) - 1);
1589 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
1591 memset(hash, 0, sizeof(hash));
1592 memcpy(hash, client->id->hash, sizeof(client->id->hash));
1597 n.new_nick = new_nick;
1600 /* Send notify to all watchers */
1601 silc_hash_table_find_foreach(server->watcher_list, hash,
1602 silc_server_check_watcher_list_foreach, &n);
1607 /* Remove the `client' from watcher list. After calling this the `client'
1608 is not watching any nicknames. */
1610 bool silc_server_del_from_watcher_list(SilcServer server,
1611 SilcClientEntry client)
1613 SilcHashTableList htl;
1615 SilcClientEntry entry;
1618 silc_hash_table_list(server->watcher_list, &htl);
1619 while (silc_hash_table_get(&htl, &key, (void **)&entry)) {
1620 if (entry == client) {
1621 silc_hash_table_del_by_context(server->watcher_list, key, client);
1624 SILC_LOG_DEBUG(("Removing %s from WATCH list",
1625 silc_id_render(client->id, SILC_ID_CLIENT)));
1627 /* Now check whether there still exists entries with this key, if not
1628 then free the key to not leak memory. */
1629 if (!silc_hash_table_find(server->watcher_list, key, NULL, NULL))
1635 silc_hash_table_list_reset(&htl);
1640 /* Force the client indicated by `chl' to change the channel user mode
1641 on channel indicated by `channel' to `forced_mode'. */
1643 bool silc_server_force_cumode_change(SilcServer server,
1644 SilcSocketConnection sock,
1645 SilcChannelEntry channel,
1646 SilcChannelClientEntry chl,
1647 SilcUInt32 forced_mode)
1649 SilcBuffer idp1, idp2;
1650 unsigned char cumode[4];
1652 SILC_LOG_DEBUG(("Enforcing sender to change mode"));
1655 silc_server_send_notify_cumode(server, sock, FALSE, channel, forced_mode,
1656 server->id, SILC_ID_SERVER,
1657 chl->client->id, NULL);
1659 idp1 = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1660 idp2 = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
1661 SILC_PUT32_MSB(forced_mode, cumode);
1662 silc_server_send_notify_to_channel(server, sock, channel, FALSE,
1663 SILC_NOTIFY_TYPE_CUMODE_CHANGE,
1664 3, idp1->data, idp1->len,
1665 cumode, sizeof(cumode),
1666 idp2->data, idp2->len);
1667 silc_buffer_free(idp1);
1668 silc_buffer_free(idp2);
1673 /* Find active socket connection by the IP address and port indicated by
1674 `ip' and `port', and socket connection type of `type'. */
1676 SilcSocketConnection
1677 silc_server_find_socket_by_host(SilcServer server,
1678 SilcSocketType type,
1679 const char *ip, SilcUInt16 port)
1683 for (i = 0; i < server->config->param.connections_max; i++) {
1684 if (!server->sockets[i])
1686 if (!strcmp(server->sockets[i]->ip, ip) &&
1687 (!port || server->sockets[i]->port == port) &&
1688 server->sockets[i]->type == type)
1689 return server->sockets[i];