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 and 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_data(client);
222 silc_idlist_del_client(server->local_list, client);
225 if (!silc_idcache_list_next(list, &id_cache))
229 silc_idcache_list_free(list);
232 if (silc_idcache_get_all(server->global_list->clients, &list)) {
234 if (silc_idcache_list_first(list, &id_cache)) {
236 client = (SilcClientEntry)id_cache->context;
238 /* If client is not registered, is not originated from `router'
239 and is not owned by `entry', skip it. */
240 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
241 client->router != router ||
242 (router != entry && !SILC_ID_COMPARE(client->id, entry->id,
243 client->id->ip.data_len))) {
244 if (!silc_idcache_list_next(list, &id_cache))
250 if (server_signoff) {
251 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
252 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
253 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
255 argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
257 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
258 memcpy(argv[argc], idp->data, idp->len);
259 argv_lens[argc] = idp->len;
260 argv_types[argc] = argc + 1;
262 silc_buffer_free(idp);
265 /* Update statistics */
266 server->stat.clients--;
267 if (server->stat.cell_clients)
268 server->stat.cell_clients--;
269 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
270 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
272 silc_server_remove_clients_channels(server, entry, clients,
274 silc_server_del_from_watcher_list(server, client);
276 /* Remove the client entry */
277 if (!server_signoff) {
278 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
279 id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
281 silc_idlist_del_data(client);
282 silc_idlist_del_client(server->global_list, client);
285 if (!silc_idcache_list_next(list, &id_cache))
289 silc_idcache_list_free(list);
292 /* Return now if we are shutting down */
293 if (server->server_shutdown) {
294 silc_hash_table_free(channels);
296 if (server_signoff) {
297 for (i = 0; i < argc; i++)
300 silc_free(argv_lens);
301 silc_free(argv_types);
302 silc_hash_table_free(clients);
307 /* Send the SERVER_SIGNOFF notify */
308 if (server_signoff) {
309 SilcBuffer args, not;
311 SILC_LOG_DEBUG(("Sending SERVER_SIGNOFF for %s with %d clients",
312 silc_id_render(entry->id, SILC_ID_SERVER), argc - 1));
314 /* Send SERVER_SIGNOFF notify to our primary router */
315 if (server->router != entry) {
316 args = silc_argument_payload_encode(1, argv, argv_lens,
318 silc_server_send_notify_args(server, SILC_PRIMARY_ROUTE(server),
319 SILC_BROADCAST(server),
320 SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
322 silc_buffer_free(args);
325 /* Send to local clients. We also send the list of client ID's that
326 is to be removed for those servers that would like to use that list. */
327 args = silc_argument_payload_encode(argc, argv, argv_lens,
329 not = silc_notify_payload_encode_args(SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
331 silc_server_packet_send_clients(server, clients,
332 SILC_PACKET_NOTIFY, 0, FALSE,
333 not->data, not->len, FALSE);
335 /* Send notify also to local backup routers */
336 silc_server_backup_send(server, NULL, SILC_PACKET_NOTIFY, 0,
337 not->data, not->len, FALSE, TRUE);
339 silc_buffer_free(args);
340 silc_buffer_free(not);
341 for (i = 0; i < argc; i++)
344 silc_free(argv_lens);
345 silc_free(argv_types);
346 silc_hash_table_free(clients);
349 /* We must now re-generate the channel key for all channels that had
350 this server's client(s) on the channel. As they left the channel we
351 must re-generate the channel key. */
352 silc_hash_table_list(channels, &htl);
353 while (silc_hash_table_get(&htl, NULL, (void **)&channel)) {
354 if (!silc_server_create_channel_key(server, channel, 0)) {
355 silc_hash_table_list_reset(&htl);
356 silc_hash_table_free(channels);
360 /* Do not send the channel key if private channel key mode is set */
361 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY || !channel->channel_key)
364 silc_server_send_channel_key(server, NULL, channel,
365 server->server_type == SILC_ROUTER ?
366 FALSE : !server->standalone);
368 silc_hash_table_list_reset(&htl);
369 silc_hash_table_free(channels);
374 static SilcServerEntry
375 silc_server_update_clients_by_real_server(SilcServer server,
376 SilcServerEntry from,
377 SilcClientEntry client,
379 SilcIDCacheEntry client_cache)
381 SilcServerEntry server_entry;
382 SilcIDCacheEntry id_cache = NULL;
383 SilcIDCacheList list;
385 if (!silc_idcache_get_all(server->local_list->servers, &list))
388 if (silc_idcache_list_first(list, &id_cache)) {
390 server_entry = (SilcServerEntry)id_cache->context;
391 if (server_entry != from &&
392 SILC_ID_COMPARE(server_entry->id, client->id,
393 client->id->ip.data_len)) {
394 SILC_LOG_DEBUG(("Found (local) %s",
395 silc_id_render(server_entry->id, SILC_ID_SERVER)));
397 if (!server_entry->data.send_key && server_entry->router) {
398 SILC_LOG_DEBUG(("Server not locally connected, use its router"));
399 /* If the client is not marked as local then move it to local list
400 since the server is local. */
402 SILC_LOG_DEBUG(("Moving client to local list"));
403 silc_idcache_add(server->local_list->clients, client_cache->name,
404 client_cache->id, client_cache->context,
405 client_cache->expire, NULL);
406 silc_idcache_del_by_context(server->global_list->clients, client);
408 server_entry = server_entry->router;
410 /* If the client is not marked as local then move it to local list
411 since the server is local. */
412 if (server_entry->server_type != SILC_BACKUP_ROUTER && !local) {
413 SILC_LOG_DEBUG(("Moving client to local list"));
414 silc_idcache_add(server->local_list->clients, client_cache->name,
415 client_cache->id, client_cache->context,
416 client_cache->expire, NULL);
417 silc_idcache_del_by_context(server->global_list->clients, client);
421 silc_idcache_list_free(list);
425 if (!silc_idcache_list_next(list, &id_cache))
430 silc_idcache_list_free(list);
432 if (!silc_idcache_get_all(server->global_list->servers, &list))
435 if (silc_idcache_list_first(list, &id_cache)) {
437 server_entry = (SilcServerEntry)id_cache->context;
438 if (server_entry != from &&
439 SILC_ID_COMPARE(server_entry->id, client->id,
440 client->id->ip.data_len)) {
441 SILC_LOG_DEBUG(("Found (global) %s",
442 silc_id_render(server_entry->id, SILC_ID_SERVER)));
444 if (!server_entry->data.send_key && server_entry->router) {
445 SILC_LOG_DEBUG(("Server not locally connected, use its router"));
446 /* If the client is marked as local then move it to global list
447 since the server is global. */
449 SILC_LOG_DEBUG(("Moving client to global list"));
450 silc_idcache_add(server->global_list->clients, client_cache->name,
451 client_cache->id, client_cache->context, 0, NULL);
452 silc_idcache_del_by_context(server->local_list->clients, client);
454 server_entry = server_entry->router;
456 /* If the client is marked as local then move it to global list
457 since the server is global. */
458 if (server_entry->server_type != SILC_BACKUP_ROUTER && local) {
459 SILC_LOG_DEBUG(("Moving client to global list"));
460 silc_idcache_add(server->global_list->clients, client_cache->name,
461 client_cache->id, client_cache->context, 0, NULL);
462 silc_idcache_del_by_context(server->local_list->clients, client);
466 silc_idcache_list_free(list);
470 if (!silc_idcache_list_next(list, &id_cache))
475 silc_idcache_list_free(list);
480 /* Updates the clients that are originated from the `from' to be originated
481 from the `to'. If the `resolve_real_server' is TRUE then this will
482 attempt to figure out which clients really are originated from the
483 `from' and which are originated from a server that we have connection
484 to, when we've acting as backup router. If it is FALSE the `to' will
485 be the new source. */
487 void silc_server_update_clients_by_server(SilcServer server,
488 SilcServerEntry from,
490 bool resolve_real_server)
492 SilcIDCacheList list = NULL;
493 SilcIDCacheEntry id_cache = NULL;
494 SilcClientEntry client = NULL;
498 if (silc_idcache_get_all(server->global_list->clients, &list)) {
499 if (silc_idcache_list_first(list, &id_cache)) {
501 client = (SilcClientEntry)id_cache->context;
503 /* If entry is disabled skip it. If entry is local to us, do not
504 switch it to anyone else, it is ours so skip it. */
505 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
506 SILC_IS_LOCAL(client)) {
507 if (!silc_idcache_list_next(list, &id_cache))
513 SILC_LOG_DEBUG(("Client %s",
514 silc_id_render(client->id, SILC_ID_CLIENT)));
516 SILC_LOG_DEBUG(("Client->router %s",
517 silc_id_render(client->router->id, SILC_ID_SERVER)));
520 if (client->router == from) {
521 if (resolve_real_server) {
523 silc_server_update_clients_by_real_server(server, from, client,
525 if (!client->router) {
526 if (server->server_type == SILC_ROUTER)
527 client->router = from;
536 /* All are changed */
541 SILC_LOG_DEBUG(("Client changed to %s",
542 silc_id_render(client->router->id, SILC_ID_CLIENT)));
544 if (!silc_idcache_list_next(list, &id_cache))
548 silc_idcache_list_free(list);
552 if (silc_idcache_get_all(server->local_list->clients, &list)) {
553 if (silc_idcache_list_first(list, &id_cache)) {
555 client = (SilcClientEntry)id_cache->context;
557 /* If entry is disabled skip it. If entry is local to us, do not
558 switch it to anyone else, it is ours so skip it. */
559 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
560 SILC_IS_LOCAL(client)) {
561 if (!silc_idcache_list_next(list, &id_cache))
567 SILC_LOG_DEBUG(("Client %s",
568 silc_id_render(client->id, SILC_ID_CLIENT)));
570 SILC_LOG_DEBUG(("Client->router %s",
571 silc_id_render(client->router->id, SILC_ID_SERVER)));
574 if (client->router == from) {
575 if (resolve_real_server) {
577 silc_server_update_clients_by_real_server(server, from, client,
580 client->router = from;
586 /* All are changed */
591 SILC_LOG_DEBUG(("Client changed to %s",
592 silc_id_render(client->router->id, SILC_ID_CLIENT)));
594 if (!silc_idcache_list_next(list, &id_cache))
598 silc_idcache_list_free(list);
602 /* Updates servers that are from `from' to be originated from `to'. This
603 will also update the server's connection to `to's connection. */
605 void silc_server_update_servers_by_server(SilcServer server,
606 SilcServerEntry from,
609 SilcIDCacheList list = NULL;
610 SilcIDCacheEntry id_cache = NULL;
611 SilcServerEntry server_entry = NULL;
613 SILC_LOG_DEBUG(("Updating servers"));
615 if (silc_idcache_get_all(server->local_list->servers, &list)) {
616 if (silc_idcache_list_first(list, &id_cache)) {
618 server_entry = (SilcServerEntry)id_cache->context;
620 /* If entry is local to us, do not switch it to any anyone else,
622 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
623 server_entry == from) {
624 if (!silc_idcache_list_next(list, &id_cache))
630 /* If we are standalone router, any server that is not directly
631 connected to cannot exist anymore. If we are not standalone
632 we update it correctly. */
633 if (server->server_type == SILC_ROUTER && server->standalone) {
634 silc_server_backup_del(server, server_entry);
635 silc_server_backup_replaced_del(server, server_entry);
636 silc_idlist_del_data(server_entry);
637 silc_idlist_del_server(server->local_list, server_entry);
638 server->stat.servers--;
639 server->stat.cell_servers--;
641 /* XXX if we are not standalone, do a check from local config
642 whether this server is in our cell, but not connected to
643 us (in which case we must remove it). */
645 if (server_entry->router == from) {
646 SILC_LOG_DEBUG(("Updating server (local) %s",
647 server_entry->server_name ?
648 server_entry->server_name : ""));
649 server_entry->router = to;
650 server_entry->connection = to->connection;
654 if (!silc_idcache_list_next(list, &id_cache))
658 silc_idcache_list_free(list);
661 if (silc_idcache_get_all(server->global_list->servers, &list)) {
662 if (silc_idcache_list_first(list, &id_cache)) {
664 server_entry = (SilcServerEntry)id_cache->context;
666 /* If entry is local to us, do not switch it to anyone else,
668 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
669 server_entry == from) {
670 if (!silc_idcache_list_next(list, &id_cache))
676 /* If we are standalone router, any server that is not directly
677 connected to cannot exist anymore. If we are not standalone
678 we update it correctly. */
679 if (server->server_type == SILC_ROUTER && server->standalone) {
680 silc_server_backup_del(server, server_entry);
681 silc_server_backup_replaced_del(server, server_entry);
682 silc_idlist_del_data(server_entry);
683 silc_idlist_del_server(server->global_list, server_entry);
684 server->stat.servers--;
685 server->stat.cell_servers--;
687 /* XXX if we are not standalone, do a check from local config
688 whether this server is in our cell, but not connected to
689 us (in which case we must remove it). */
691 if (server_entry->router == from) {
692 SILC_LOG_DEBUG(("Updating server (global) %s",
693 server_entry->server_name ?
694 server_entry->server_name : ""));
695 server_entry->router = to;
696 server_entry->connection = to->connection;
700 if (!silc_idcache_list_next(list, &id_cache))
704 silc_idcache_list_free(list);
709 /* Toggles the enabled/disabled status of local server connections. Packets
710 can be sent to the servers when `toggle_enabled' is TRUE and will be
711 dropped if `toggle_enabled' is FALSE, after this function is called. */
713 void silc_server_local_servers_toggle_enabled(SilcServer server,
716 SilcIDCacheList list = NULL;
717 SilcIDCacheEntry id_cache = NULL;
718 SilcServerEntry server_entry = NULL;
720 if (silc_idcache_get_all(server->local_list->servers, &list)) {
721 if (silc_idcache_list_first(list, &id_cache)) {
723 server_entry = (SilcServerEntry)id_cache->context;
724 if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry) {
725 if (!silc_idcache_list_next(list, &id_cache))
732 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
734 server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
736 if (!silc_idcache_list_next(list, &id_cache))
740 silc_idcache_list_free(list);
743 if (silc_idcache_get_all(server->global_list->servers, &list)) {
744 if (silc_idcache_list_first(list, &id_cache)) {
746 server_entry = (SilcServerEntry)id_cache->context;
747 if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry) {
748 if (!silc_idcache_list_next(list, &id_cache))
755 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
757 server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
759 if (!silc_idcache_list_next(list, &id_cache))
763 silc_idcache_list_free(list);
767 /* Removes servers that are originated from the `from'. The server
768 entry is deleted in this function. If `remove_clients' is TRUE then
769 all clients originated from the server are removed too, and server
770 signoff is sent. Note that this does not remove the `from'. This
771 also does not remove locally connected servers. */
773 void silc_server_remove_servers_by_server(SilcServer server,
774 SilcServerEntry from,
777 SilcIDCacheList list = NULL;
778 SilcIDCacheEntry id_cache = NULL;
779 SilcServerEntry server_entry = NULL;
781 SILC_LOG_DEBUG(("Removing servers by %s",
782 from->server_name ? from->server_name : "server"));
784 if (silc_idcache_get_all(server->local_list->servers, &list)) {
785 if (silc_idcache_list_first(list, &id_cache)) {
787 server_entry = (SilcServerEntry)id_cache->context;
788 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
789 server_entry->router != from || server_entry == from) {
790 if (!silc_idcache_list_next(list, &id_cache))
796 /* Remove clients owned by this server */
798 silc_server_remove_clients_by_server(server, from, server_entry,
801 /* Remove the server */
802 silc_idlist_del_server(server->local_list, server_entry);
804 if (!silc_idcache_list_next(list, &id_cache))
808 silc_idcache_list_free(list);
811 if (silc_idcache_get_all(server->global_list->servers, &list)) {
812 if (silc_idcache_list_first(list, &id_cache)) {
814 server_entry = (SilcServerEntry)id_cache->context;
815 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
816 server_entry->router != from || server_entry == from) {
817 if (!silc_idcache_list_next(list, &id_cache))
823 /* Remove clients owned by this server */
825 silc_server_remove_clients_by_server(server, from, server_entry,
828 /* Remove the server */
829 silc_idlist_del_server(server->global_list, server_entry);
831 if (!silc_idcache_list_next(list, &id_cache))
835 silc_idcache_list_free(list);
839 /* Removes channels that are from `from. */
841 void silc_server_remove_channels_by_server(SilcServer server,
842 SilcServerEntry from)
844 SilcIDCacheList list = NULL;
845 SilcIDCacheEntry id_cache = NULL;
846 SilcChannelEntry channel = NULL;
848 SILC_LOG_DEBUG(("Removing channels by server"));
850 if (silc_idcache_get_all(server->global_list->channels, &list)) {
851 if (silc_idcache_list_first(list, &id_cache)) {
853 channel = (SilcChannelEntry)id_cache->context;
854 if (channel->router == from)
855 silc_idlist_del_channel(server->global_list, channel);
856 if (!silc_idcache_list_next(list, &id_cache))
860 silc_idcache_list_free(list);
864 /* Updates channels that are from `from' to be originated from `to'. */
866 void silc_server_update_channels_by_server(SilcServer server,
867 SilcServerEntry from,
870 SilcIDCacheList list = NULL;
871 SilcIDCacheEntry id_cache = NULL;
872 SilcChannelEntry channel = NULL;
874 SILC_LOG_DEBUG(("Updating channels by server"));
876 if (silc_idcache_get_all(server->global_list->channels, &list)) {
877 if (silc_idcache_list_first(list, &id_cache)) {
879 channel = (SilcChannelEntry)id_cache->context;
880 if (channel->router == from)
881 channel->router = to;
882 if (!silc_idcache_list_next(list, &id_cache))
886 silc_idcache_list_free(list);
890 /* Checks whether given channel has global users. If it does this returns
891 TRUE and FALSE if there is only locally connected clients on the channel. */
893 bool silc_server_channel_has_global(SilcChannelEntry channel)
895 SilcChannelClientEntry chl;
896 SilcHashTableList htl;
898 silc_hash_table_list(channel->user_list, &htl);
899 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
900 if (chl->client->router) {
901 silc_hash_table_list_reset(&htl);
905 silc_hash_table_list_reset(&htl);
910 /* Checks whether given channel has locally connected users. If it does this
911 returns TRUE and FALSE if there is not one locally connected client. */
913 bool silc_server_channel_has_local(SilcChannelEntry channel)
915 SilcChannelClientEntry chl;
916 SilcHashTableList htl;
918 silc_hash_table_list(channel->user_list, &htl);
919 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
920 if (!chl->client->router) {
921 silc_hash_table_list_reset(&htl);
925 silc_hash_table_list_reset(&htl);
930 /* This function removes the channel and all users on the channel, unless
931 the channel is permanent. In this case the channel is disabled but all
932 users are removed from the channel. Returns TRUE if the channel is
933 destroyed totally, and FALSE if it is permanent and remains. */
935 bool silc_server_channel_delete(SilcServer server,
936 SilcChannelEntry channel)
938 SilcChannelClientEntry chl;
939 SilcHashTableList htl;
940 bool delchan = !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH);
943 /* Update statistics */
944 if (server->server_type == SILC_ROUTER)
945 server->stat.chanclients -= channel->user_count;
947 /* Totally delete the channel and all users on the channel. The
948 users are deleted automatically in silc_idlist_del_channel. */
949 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
950 if (silc_idlist_del_channel(server->local_list, channel)) {
951 server->stat.my_channels--;
952 if (server->server_type == SILC_ROUTER) {
953 server->stat.channels--;
954 server->stat.cell_channels--;
957 if (silc_idlist_del_channel(server->global_list, channel))
958 if (server->server_type == SILC_ROUTER)
959 server->stat.channels--;
965 /* Channel is permanent, do not remove it, remove only users */
966 channel->disabled = TRUE;
967 silc_hash_table_list(channel->user_list, &htl);
968 while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
969 silc_hash_table_del(chl->client->channels, channel);
970 silc_hash_table_del(channel->user_list, chl->client);
971 channel->user_count--;
973 /* Update statistics */
974 if (SILC_IS_LOCAL(chl->client))
975 server->stat.my_chanclients--;
976 if (server->server_type == SILC_ROUTER) {
977 server->stat.cell_chanclients--;
978 server->stat.chanclients--;
983 silc_hash_table_list_reset(&htl);
985 SILC_LOG_DEBUG(("Channel %s remains", channel->channel_name));
990 /* Returns TRUE if the given client is on the channel. FALSE if not.
991 This works because we assure that the user list on the channel is
992 always in up to date thus we can only check the channel list from
993 `client' which is faster than checking the user list from `channel'. */
995 bool silc_server_client_on_channel(SilcClientEntry client,
996 SilcChannelEntry channel,
997 SilcChannelClientEntry *chl)
999 if (!client || !channel)
1002 return silc_hash_table_find(client->channels, channel, NULL,
1006 /* Checks string for bad characters and returns TRUE if they are found. */
1008 bool silc_server_name_bad_chars(const char *name, SilcUInt32 name_len)
1012 for (i = 0; i < name_len; i++) {
1013 if (!isascii(name[i]))
1015 if (name[i] <= 32) return TRUE;
1016 if (name[i] == ' ') return TRUE;
1017 if (name[i] == '*') return TRUE;
1018 if (name[i] == '?') return TRUE;
1019 if (name[i] == ',') return TRUE;
1025 /* Modifies the `name' if it includes bad characters and returns new
1026 allocated name that does not include bad characters. */
1028 char *silc_server_name_modify_bad(const char *name, SilcUInt32 name_len)
1031 char *newname = strdup(name);
1033 for (i = 0; i < name_len; i++) {
1034 if (!isascii(newname[i])) newname[i] = '_';
1035 if (newname[i] <= 32) newname[i] = '_';
1036 if (newname[i] == ' ') newname[i] = '_';
1037 if (newname[i] == '*') newname[i] = '_';
1038 if (newname[i] == '?') newname[i] = '_';
1039 if (newname[i] == ',') newname[i] = '_';
1045 /* Find number of sockets by IP address indicated by `ip'. Returns 0 if
1046 socket connections with the IP address does not exist. */
1048 SilcUInt32 silc_server_num_sockets_by_ip(SilcServer server, const char *ip,
1049 SilcSocketType type)
1053 for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
1054 if (server->sockets[i] && !SILC_IS_LISTENER(server->sockets[i]) &&
1055 !strcmp(server->sockets[i]->ip, ip) &&
1056 server->sockets[i]->type == type)
1063 /* Find number of sockets by IP address indicated by remote host, indicatd
1064 by `ip' or `hostname', `port', and `type'. Returns 0 if socket connections
1065 does not exist. If `ip' is provided then `hostname' is ignored. */
1067 SilcUInt32 silc_server_num_sockets_by_remote(SilcServer server,
1069 const char *hostname,
1071 SilcSocketType type)
1075 if (!ip && !hostname)
1078 for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
1079 if (server->sockets[i] && !SILC_IS_LISTENER(server->sockets[i]) &&
1080 ((ip && !strcmp(server->sockets[i]->ip, ip)) ||
1081 (hostname && !strcmp(server->sockets[i]->hostname, hostname))) &&
1082 server->sockets[i]->port == port &&
1083 server->sockets[i]->type == type)
1090 /* Finds locally cached public key by the public key received in the SKE.
1091 If we have it locally cached then we trust it and will use it in the
1092 authentication protocol. Returns the locally cached public key or NULL
1093 if we do not find the public key. */
1095 SilcPublicKey silc_server_find_public_key(SilcServer server,
1096 SilcHashTable local_public_keys,
1097 SilcPublicKey remote_public_key)
1099 SilcPublicKey cached_key;
1101 SILC_LOG_DEBUG(("Find remote public key (%d keys in local cache)",
1102 silc_hash_table_count(local_public_keys)));
1104 if (!silc_hash_table_find_ext(local_public_keys, remote_public_key,
1105 (void **)&cached_key, NULL,
1106 silc_hash_public_key, NULL,
1107 silc_hash_public_key_compare, NULL)) {
1108 SILC_LOG_ERROR(("Public key not found"));
1112 SILC_LOG_DEBUG(("Found public key"));
1117 /* This returns the first public key from the table of public keys. This
1118 is used only in cases where single public key exists in the table and
1119 we want to get a pointer to it. For public key tables that has multiple
1120 keys in it the silc_server_find_public_key must be used. */
1122 SilcPublicKey silc_server_get_public_key(SilcServer server,
1123 SilcHashTable local_public_keys)
1125 SilcPublicKey cached_key;
1126 SilcHashTableList htl;
1128 SILC_LOG_DEBUG(("Start"));
1130 assert(silc_hash_table_count(local_public_keys) < 2);
1132 silc_hash_table_list(local_public_keys, &htl);
1133 if (!silc_hash_table_get(&htl, NULL, (void **)&cached_key))
1135 silc_hash_table_list_reset(&htl);
1140 /* Check whether the connection `sock' is allowed to connect to us. This
1141 checks for example whether there is too much connections for this host,
1142 and required version for the host etc. */
1144 bool silc_server_connection_allowed(SilcServer server,
1145 SilcSocketConnection sock,
1146 SilcSocketType type,
1147 SilcServerConfigConnParams *global,
1148 SilcServerConfigConnParams *params,
1151 SilcUInt32 conn_number = (type == SILC_SOCKET_TYPE_CLIENT ?
1152 server->stat.my_clients :
1153 type == SILC_SOCKET_TYPE_SERVER ?
1154 server->stat.my_servers :
1155 server->stat.my_routers);
1156 SilcUInt32 num_sockets, max_hosts, max_per_host;
1157 SilcUInt32 r_protocol_version, l_protocol_version;
1158 SilcUInt32 r_software_version, l_software_version;
1159 char *r_vendor_version = NULL, *l_vendor_version;
1161 SILC_LOG_DEBUG(("Checking whether connection is allowed"));
1165 l_protocol_version =
1166 silc_version_to_num(params && params->version_protocol ?
1167 params->version_protocol :
1168 global->version_protocol);
1169 l_software_version =
1170 silc_version_to_num(params && params->version_software ?
1171 params->version_software :
1172 global->version_software);
1173 l_vendor_version = (params && params->version_software_vendor ?
1174 params->version_software_vendor :
1175 global->version_software_vendor);
1177 if (ske && silc_ske_parse_version(ske, &r_protocol_version, NULL,
1178 &r_software_version, NULL,
1179 &r_vendor_version)) {
1180 sock->version = r_protocol_version;
1182 /* Match protocol version */
1183 if (l_protocol_version && r_protocol_version &&
1184 r_protocol_version < l_protocol_version) {
1185 SILC_LOG_INFO(("Connection %s (%s) is too old version",
1186 sock->hostname, sock->ip));
1187 silc_server_disconnect_remote(server, sock,
1188 SILC_STATUS_ERR_BAD_VERSION,
1189 "You support too old protocol version");
1193 /* Math software version */
1194 if (l_software_version && r_software_version &&
1195 r_software_version < l_software_version) {
1196 SILC_LOG_INFO(("Connection %s (%s) is too old version",
1197 sock->hostname, sock->ip));
1198 silc_server_disconnect_remote(server, sock,
1199 SILC_STATUS_ERR_BAD_VERSION,
1200 "You support too old software version");
1204 /* Regex match vendor version */
1205 if (l_vendor_version && r_vendor_version &&
1206 !silc_string_match(l_vendor_version, r_vendor_version)) {
1207 SILC_LOG_INFO(("Connection %s (%s) is unsupported version",
1208 sock->hostname, sock->ip));
1209 silc_server_disconnect_remote(server, sock,
1210 SILC_STATUS_ERR_BAD_VERSION,
1211 "Your software is not supported");
1215 silc_free(r_vendor_version);
1217 /* Check for maximum connections limit */
1219 num_sockets = silc_server_num_sockets_by_ip(server, sock->ip, type);
1220 max_hosts = (params ? params->connections_max : global->connections_max);
1221 max_per_host = (params ? params->connections_max_per_host :
1222 global->connections_max_per_host);
1224 if (max_hosts && conn_number >= max_hosts) {
1225 SILC_LOG_INFO(("Server is full, closing %s (%s) connection",
1226 sock->hostname, sock->ip));
1227 silc_server_disconnect_remote(server, sock,
1228 SILC_STATUS_ERR_RESOURCE_LIMIT,
1229 "Server is full, try again later");
1233 if (num_sockets >= max_per_host) {
1234 SILC_LOG_INFO(("Too many connections from %s (%s), closing connection",
1235 sock->hostname, sock->ip));
1236 silc_server_disconnect_remote(server, sock,
1237 SILC_STATUS_ERR_RESOURCE_LIMIT,
1238 "Too many connections from your host");
1245 /* Checks that client has rights to add or remove channel modes. If any
1246 of the checks fails FALSE is returned. */
1248 bool silc_server_check_cmode_rights(SilcServer server,
1249 SilcChannelEntry channel,
1250 SilcChannelClientEntry client,
1253 bool is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1254 bool is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1256 /* Check whether has rights to change anything */
1257 if (!is_op && !is_fo)
1260 /* Check whether has rights to change everything */
1264 /* Founder implies operator */
1268 /* We know that client is channel operator, check that they are not
1269 changing anything that requires channel founder rights. Rest of the
1270 modes are available automatically for channel operator. */
1272 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1273 if (is_op && !is_fo)
1276 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1277 if (is_op && !is_fo)
1282 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1283 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
1284 if (is_op && !is_fo)
1288 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1289 if (is_op && !is_fo)
1294 if (mode & SILC_CHANNEL_MODE_CIPHER) {
1295 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
1296 if (is_op && !is_fo)
1300 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1301 if (is_op && !is_fo)
1306 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1307 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
1308 if (is_op && !is_fo)
1312 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1313 if (is_op && !is_fo)
1318 if (mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1319 if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS)) {
1320 if (is_op && !is_fo)
1324 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1325 if (is_op && !is_fo)
1330 if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1331 if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS)) {
1332 if (is_op && !is_fo)
1336 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1337 if (is_op && !is_fo)
1345 /* Check that the client has rights to change its user mode. Returns
1346 FALSE if setting some mode is not allowed. */
1348 bool silc_server_check_umode_rights(SilcServer server,
1349 SilcClientEntry client,
1352 bool server_op = FALSE, router_op = FALSE;
1354 if (mode & SILC_UMODE_SERVER_OPERATOR) {
1355 /* Cannot set server operator mode (must use OPER command) */
1356 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR))
1359 /* Remove the server operator rights */
1360 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
1364 if (mode & SILC_UMODE_ROUTER_OPERATOR) {
1365 /* Cannot set router operator mode (must use SILCOPER command) */
1366 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR))
1369 /* Remove the router operator rights */
1370 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
1375 SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR);
1377 SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR);
1382 /* This function is used to send the notify packets and motd to the
1383 incoming client connection. */
1385 void silc_server_send_connect_notifys(SilcServer server,
1386 SilcSocketConnection sock,
1387 SilcClientEntry client)
1389 SilcIDListData idata = (SilcIDListData)client;
1391 SILC_LOG_DEBUG(("Send welcome notifys"));
1393 /* Send some nice info to the client */
1394 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1395 ("Welcome to the SILC Network %s",
1397 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1398 ("Your host is %s, running version %s",
1399 server->server_name, server_version));
1401 if (server->server_type == SILC_ROUTER) {
1402 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1403 ("There are %d clients, %d servers and %d "
1404 "routers in SILC Network",
1405 server->stat.clients, server->stat.servers + 1,
1406 server->stat.routers));
1408 if (server->stat.clients && server->stat.servers + 1)
1409 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1410 ("There are %d clients, %d servers and %d "
1411 "routers in SILC Network",
1412 server->stat.clients, server->stat.servers + 1,
1413 (server->standalone ? 0 :
1414 !server->stat.routers ? 1 :
1415 server->stat.routers)));
1418 if (server->stat.cell_clients && server->stat.cell_servers + 1)
1419 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1420 ("There are %d clients on %d server in our cell",
1421 server->stat.cell_clients,
1422 server->stat.cell_servers + 1));
1423 if (server->server_type == SILC_ROUTER) {
1424 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1425 ("I have %d clients, %d channels, %d servers and "
1427 server->stat.my_clients,
1428 server->stat.my_channels,
1429 server->stat.my_servers,
1430 server->stat.my_routers));
1432 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1433 ("I have %d clients and %d channels formed",
1434 server->stat.my_clients,
1435 server->stat.my_channels));
1438 if (server->stat.server_ops || server->stat.router_ops)
1439 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1440 ("There are %d server operators and %d router "
1442 server->stat.server_ops,
1443 server->stat.router_ops));
1444 if (server->stat.my_router_ops + server->stat.my_server_ops)
1445 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1446 ("I have %d operators online",
1447 server->stat.my_router_ops +
1448 server->stat.my_server_ops));
1450 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1451 ("Your connection is secured with %s cipher, "
1452 "key length %d bits",
1453 idata->send_key->cipher->name,
1454 idata->send_key->cipher->key_len));
1455 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1456 ("Your current nickname is %s",
1460 silc_server_send_motd(server, sock);
1463 /* Kill the client indicated by `remote_client' sending KILLED notify
1464 to the client, to all channels client has joined and to primary
1465 router if needed. The killed client is also removed from all channels. */
1467 void silc_server_kill_client(SilcServer server,
1468 SilcClientEntry remote_client,
1469 const char *comment,
1471 SilcIdType killer_id_type)
1473 SilcBuffer killed, killer;
1475 SILC_LOG_DEBUG(("Killing client %s",
1476 silc_id_render(remote_client->id, SILC_ID_CLIENT)));
1478 /* Send the KILL notify packets. First send it to the channel, then
1479 to our primary router and then directly to the client who is being
1480 killed right now. */
1482 killed = silc_id_payload_encode(remote_client->id, SILC_ID_CLIENT);
1483 killer = silc_id_payload_encode(killer_id, killer_id_type);
1485 /* Send KILLED notify to the channels. It is not sent to the client
1486 as it will be sent differently destined directly to the client and not
1488 silc_server_send_notify_on_channels(server, remote_client,
1489 remote_client, SILC_NOTIFY_TYPE_KILLED,
1490 3, killed->data, killed->len,
1491 comment, comment ? strlen(comment) : 0,
1492 killer->data, killer->len);
1494 /* Send KILLED notify to primary route */
1495 silc_server_send_notify_killed(server, SILC_PRIMARY_ROUTE(server),
1496 SILC_BROADCAST(server), remote_client->id,
1497 comment, killer_id, killer_id_type);
1499 /* Send KILLED notify to the client directly */
1500 if (remote_client->connection || remote_client->router)
1501 silc_server_send_notify_killed(server, remote_client->connection ?
1502 remote_client->connection :
1503 remote_client->router->connection, FALSE,
1504 remote_client->id, comment,
1505 killer_id, killer_id_type);
1507 /* Remove the client from all channels. This generates new keys to the
1508 channels as well. */
1509 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
1512 /* Remove the client entry, If it is locally connected then we will also
1513 disconnect the client here */
1514 if (remote_client->connection) {
1515 /* Remove locally conneted client */
1516 SilcSocketConnection sock = remote_client->connection;
1517 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
1518 silc_server_close_connection(server, sock);
1520 /* Update statistics */
1521 server->stat.clients--;
1522 if (server->stat.cell_clients)
1523 server->stat.cell_clients--;
1524 SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
1525 SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
1527 if (SILC_IS_LOCAL(remote_client)) {
1528 server->stat.my_clients--;
1529 silc_schedule_task_del_by_context(server->schedule, remote_client);
1530 silc_idlist_del_data(remote_client);
1533 /* Remove remote client */
1534 silc_idlist_del_data(remote_client);
1535 if (!silc_idlist_del_client(server->global_list, remote_client)) {
1536 /* Remove this client from watcher list if it is */
1537 silc_server_del_from_watcher_list(server, remote_client);
1538 silc_idlist_del_client(server->local_list, remote_client);
1542 silc_buffer_free(killer);
1543 silc_buffer_free(killed);
1548 SilcClientEntry client;
1549 SilcNotifyType notify;
1550 const char *new_nick;
1551 } WatcherNotifyContext;
1554 silc_server_check_watcher_list_foreach(void *key, void *context,
1557 WatcherNotifyContext *notify = user_context;
1558 SilcClientEntry entry = context;
1559 SilcSocketConnection sock;
1561 if (entry == notify->client)
1564 sock = silc_server_get_client_route(notify->server, NULL, 0, entry->id,
1567 SILC_LOG_DEBUG(("Sending WATCH notify to %s",
1568 silc_id_render(entry->id, SILC_ID_CLIENT)));
1570 /* Send the WATCH notify */
1571 silc_server_send_notify_watch(notify->server, sock, entry,
1573 notify->new_nick ? notify->new_nick :
1574 (const char *)notify->client->nickname,
1579 /* This function checks whether the `client' nickname is being watched
1580 by someone, and notifies the watcher of the notify change of notify
1581 type indicated by `notify'. */
1583 bool silc_server_check_watcher_list(SilcServer server,
1584 SilcClientEntry client,
1585 const char *new_nick,
1586 SilcNotifyType notify)
1588 unsigned char hash[16];
1589 WatcherNotifyContext n;
1591 SILC_LOG_DEBUG(("Checking watcher list %s",
1592 client->nickname ? client->nickname : (unsigned char *)""));
1594 /* If the watching is rejected by the client do nothing */
1595 if (client->mode & SILC_UMODE_REJECT_WATCHING)
1598 /* Make hash from the nick, or take it from Client ID */
1599 if (client->nickname) {
1601 memset(nick, 0, sizeof(nick));
1602 silc_to_lower(client->nickname, nick, sizeof(nick) - 1);
1603 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
1605 memset(hash, 0, sizeof(hash));
1606 memcpy(hash, client->id->hash, sizeof(client->id->hash));
1611 n.new_nick = new_nick;
1614 /* Send notify to all watchers */
1615 silc_hash_table_find_foreach(server->watcher_list, hash,
1616 silc_server_check_watcher_list_foreach, &n);
1621 /* Remove the `client' from watcher list. After calling this the `client'
1622 is not watching any nicknames. */
1624 bool silc_server_del_from_watcher_list(SilcServer server,
1625 SilcClientEntry client)
1627 SilcHashTableList htl;
1629 SilcClientEntry entry;
1632 silc_hash_table_list(server->watcher_list, &htl);
1633 while (silc_hash_table_get(&htl, &key, (void **)&entry)) {
1634 if (entry == client) {
1635 silc_hash_table_del_by_context(server->watcher_list, key, client);
1638 SILC_LOG_DEBUG(("Removing %s from WATCH list",
1639 silc_id_render(client->id, SILC_ID_CLIENT)));
1641 /* Now check whether there still exists entries with this key, if not
1642 then free the key to not leak memory. */
1643 if (!silc_hash_table_find(server->watcher_list, key, NULL, NULL))
1649 silc_hash_table_list_reset(&htl);
1654 /* Force the client indicated by `chl' to change the channel user mode
1655 on channel indicated by `channel' to `forced_mode'. */
1657 bool silc_server_force_cumode_change(SilcServer server,
1658 SilcSocketConnection sock,
1659 SilcChannelEntry channel,
1660 SilcChannelClientEntry chl,
1661 SilcUInt32 forced_mode)
1663 SilcBuffer idp1, idp2;
1664 unsigned char cumode[4];
1666 SILC_LOG_DEBUG(("Enforcing sender to change mode"));
1669 silc_server_send_notify_cumode(server, sock, FALSE, channel, forced_mode,
1670 server->id, SILC_ID_SERVER,
1671 chl->client->id, NULL);
1673 idp1 = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1674 idp2 = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
1675 SILC_PUT32_MSB(forced_mode, cumode);
1676 silc_server_send_notify_to_channel(server, sock, channel, FALSE,
1677 SILC_NOTIFY_TYPE_CUMODE_CHANGE,
1678 3, idp1->data, idp1->len,
1679 cumode, sizeof(cumode),
1680 idp2->data, idp2->len);
1681 silc_buffer_free(idp1);
1682 silc_buffer_free(idp2);
1687 /* Find active socket connection by the IP address and port indicated by
1688 `ip' and `port', and socket connection type of `type'. */
1690 SilcSocketConnection
1691 silc_server_find_socket_by_host(SilcServer server,
1692 SilcSocketType type,
1693 const char *ip, SilcUInt16 port)
1697 for (i = 0; i < server->config->param.connections_max; i++) {
1698 if (!server->sockets[i])
1700 if (!strcmp(server->sockets[i]->ip, ip) &&
1701 (!port || server->sockets[i]->port == port) &&
1702 server->sockets[i]->type == type)
1703 return server->sockets[i];