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_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 or 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 silc_buffer_free(args);
336 silc_buffer_free(not);
337 for (i = 0; i < argc; i++)
340 silc_free(argv_lens);
341 silc_free(argv_types);
342 silc_hash_table_free(clients);
345 /* We must now re-generate the channel key for all channels that had
346 this server's client(s) on the channel. As they left the channel we
347 must re-generate the channel key. */
348 silc_hash_table_list(channels, &htl);
349 while (silc_hash_table_get(&htl, NULL, (void **)&channel)) {
350 if (!silc_server_create_channel_key(server, channel, 0)) {
351 silc_hash_table_list_reset(&htl);
352 silc_hash_table_free(channels);
356 /* Do not send the channel key if private channel key mode is set */
357 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY)
360 silc_server_send_channel_key(server, NULL, channel,
361 server->server_type == SILC_ROUTER ?
362 FALSE : !server->standalone);
364 silc_hash_table_list_reset(&htl);
365 silc_hash_table_free(channels);
370 static SilcServerEntry
371 silc_server_update_clients_by_real_server(SilcServer server,
372 SilcServerEntry from,
373 SilcClientEntry client,
375 SilcIDCacheEntry client_cache)
377 SilcServerEntry server_entry;
378 SilcIDCacheEntry id_cache = NULL;
379 SilcIDCacheList list;
381 if (!silc_idcache_get_all(server->local_list->servers, &list))
384 if (silc_idcache_list_first(list, &id_cache)) {
386 server_entry = (SilcServerEntry)id_cache->context;
387 if (server_entry != from &&
388 SILC_ID_COMPARE(server_entry->id, client->id,
389 client->id->ip.data_len)) {
390 SILC_LOG_DEBUG(("Found (local) %s",
391 silc_id_render(server_entry->id, SILC_ID_SERVER)));
393 if (!server_entry->data.send_key && server_entry->router) {
394 SILC_LOG_DEBUG(("Server not locally connected, use its router"));
395 /* If the client is not marked as local then move it to local list
396 since the server is 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);
404 server_entry = server_entry->router;
406 /* If the client is not marked as local then move it to local list
407 since the server is local. */
408 if (server_entry->server_type != SILC_BACKUP_ROUTER && !local) {
409 SILC_LOG_DEBUG(("Moving client to local list"));
410 silc_idcache_add(server->local_list->clients, client_cache->name,
411 client_cache->id, client_cache->context,
412 client_cache->expire, NULL);
413 silc_idcache_del_by_context(server->global_list->clients, client);
417 silc_idcache_list_free(list);
421 if (!silc_idcache_list_next(list, &id_cache))
426 silc_idcache_list_free(list);
428 if (!silc_idcache_get_all(server->global_list->servers, &list))
431 if (silc_idcache_list_first(list, &id_cache)) {
433 server_entry = (SilcServerEntry)id_cache->context;
434 if (server_entry != from &&
435 SILC_ID_COMPARE(server_entry->id, client->id,
436 client->id->ip.data_len)) {
437 SILC_LOG_DEBUG(("Found (global) %s",
438 silc_id_render(server_entry->id, SILC_ID_SERVER)));
440 if (!server_entry->data.send_key && server_entry->router) {
441 SILC_LOG_DEBUG(("Server not locally connected, use its router"));
442 /* If the client is marked as local then move it to global list
443 since the server is global. */
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);
451 server_entry = server_entry->router;
453 /* If the client is marked as local then move it to global list
454 since the server is global. */
455 if (server_entry->server_type != SILC_BACKUP_ROUTER && local) {
456 SILC_LOG_DEBUG(("Moving client to global list"));
457 silc_idcache_add(server->global_list->clients, client_cache->name,
458 client_cache->id, client_cache->context,
459 client_cache->expire, NULL);
460 silc_idcache_del_by_context(server->local_list->clients, client);
464 silc_idcache_list_free(list);
468 if (!silc_idcache_list_next(list, &id_cache))
473 silc_idcache_list_free(list);
478 /* Updates the clients that are originated from the `from' to be originated
479 from the `to'. If the `resolve_real_server' is TRUE then this will
480 attempt to figure out which clients really are originated from the
481 `from' and which are originated from a server that we have connection
482 to, when we've acting as backup router. If it is FALSE the `to' will
483 be the new source. */
485 void silc_server_update_clients_by_server(SilcServer server,
486 SilcServerEntry from,
488 bool resolve_real_server)
490 SilcIDCacheList list = NULL;
491 SilcIDCacheEntry id_cache = NULL;
492 SilcClientEntry client = NULL;
496 if (silc_idcache_get_all(server->global_list->clients, &list)) {
497 if (silc_idcache_list_first(list, &id_cache)) {
499 client = (SilcClientEntry)id_cache->context;
501 /* If entry is disabled skip it. If entry is local to us, do not
502 switch it to anyone else, it is ours so skip it. */
503 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
504 SILC_IS_LOCAL(client)) {
505 if (!silc_idcache_list_next(list, &id_cache))
511 SILC_LOG_DEBUG(("Client %s",
512 silc_id_render(client->id, SILC_ID_CLIENT)));
514 SILC_LOG_DEBUG(("Client->router %s",
515 silc_id_render(client->router->id, SILC_ID_SERVER)));
518 if (client->router == from) {
519 if (resolve_real_server) {
521 silc_server_update_clients_by_real_server(server, from, client,
523 if (!client->router) {
524 if (server->server_type == SILC_ROUTER)
525 client->router = from;
534 /* All are changed */
539 SILC_LOG_DEBUG(("Client changed to %s",
540 silc_id_render(client->router->id, SILC_ID_CLIENT)));
542 if (!silc_idcache_list_next(list, &id_cache))
546 silc_idcache_list_free(list);
550 if (silc_idcache_get_all(server->local_list->clients, &list)) {
551 if (silc_idcache_list_first(list, &id_cache)) {
553 client = (SilcClientEntry)id_cache->context;
555 /* If entry is disabled skip it. If entry is local to us, do not
556 switch it to anyone else, it is ours so skip it. */
557 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
558 SILC_IS_LOCAL(client)) {
559 if (!silc_idcache_list_next(list, &id_cache))
565 SILC_LOG_DEBUG(("Client %s",
566 silc_id_render(client->id, SILC_ID_CLIENT)));
568 SILC_LOG_DEBUG(("Client->router %s",
569 silc_id_render(client->router->id, SILC_ID_SERVER)));
572 if (client->router == from) {
573 if (resolve_real_server) {
575 silc_server_update_clients_by_real_server(server, from, client,
578 client->router = from;
584 /* All are changed */
589 SILC_LOG_DEBUG(("Client changed to %s",
590 silc_id_render(client->router->id, SILC_ID_CLIENT)));
592 if (!silc_idcache_list_next(list, &id_cache))
596 silc_idcache_list_free(list);
600 /* Updates servers that are from `from' to be originated from `to'. This
601 will also update the server's connection to `to's connection. */
603 void silc_server_update_servers_by_server(SilcServer server,
604 SilcServerEntry from,
607 SilcIDCacheList list = NULL;
608 SilcIDCacheEntry id_cache = NULL;
609 SilcServerEntry server_entry = NULL;
611 SILC_LOG_DEBUG(("Updating servers"));
613 if (silc_idcache_get_all(server->local_list->servers, &list)) {
614 if (silc_idcache_list_first(list, &id_cache)) {
616 server_entry = (SilcServerEntry)id_cache->context;
618 /* If entry is local to us, do not switch it to any anyone else,
620 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
621 server_entry == from) {
622 if (!silc_idcache_list_next(list, &id_cache))
628 /* If we are standalone router, any server that is not directly
629 connected to cannot exist anymore. If we are not standalone
630 we update it correctly. */
631 if (server->server_type == SILC_ROUTER && server->standalone) {
632 silc_server_backup_del(server, server_entry);
633 silc_server_backup_replaced_del(server, server_entry);
634 silc_idlist_del_data(server_entry);
635 silc_idlist_del_server(server->local_list, server_entry);
636 server->stat.servers--;
637 server->stat.cell_servers--;
639 /* XXX if we are not standalone, do a check from local config
640 whether this server is in our cell, but not connected to
641 us (in which case we must remove it). */
643 if (server_entry->router == from) {
644 SILC_LOG_DEBUG(("Updating server (local) %s",
645 server_entry->server_name ?
646 server_entry->server_name : ""));
647 server_entry->router = to;
648 server_entry->connection = to->connection;
652 if (!silc_idcache_list_next(list, &id_cache))
656 silc_idcache_list_free(list);
659 if (silc_idcache_get_all(server->global_list->servers, &list)) {
660 if (silc_idcache_list_first(list, &id_cache)) {
662 server_entry = (SilcServerEntry)id_cache->context;
664 /* If entry is local to us, do not switch it to anyone else,
666 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
667 server_entry == from) {
668 if (!silc_idcache_list_next(list, &id_cache))
674 /* If we are standalone router, any server that is not directly
675 connected to cannot exist anymore. If we are not standalone
676 we update it correctly. */
677 if (server->server_type == SILC_ROUTER && server->standalone) {
678 silc_server_backup_del(server, server_entry);
679 silc_server_backup_replaced_del(server, server_entry);
680 silc_idlist_del_data(server_entry);
681 silc_idlist_del_server(server->global_list, server_entry);
682 server->stat.servers--;
683 server->stat.cell_servers--;
685 /* XXX if we are not standalone, do a check from local config
686 whether this server is in our cell, but not connected to
687 us (in which case we must remove it). */
689 if (server_entry->router == from) {
690 SILC_LOG_DEBUG(("Updating server (global) %s",
691 server_entry->server_name ?
692 server_entry->server_name : ""));
693 server_entry->router = to;
694 server_entry->connection = to->connection;
698 if (!silc_idcache_list_next(list, &id_cache))
702 silc_idcache_list_free(list);
707 /* Toggles the enabled/disabled status of local server connections. Packets
708 can be sent to the servers when `toggle_enabled' is TRUE and will be
709 dropped if `toggle_enabled' is FALSE, after this function is called. */
711 void silc_server_local_servers_toggle_enabled(SilcServer server,
714 SilcIDCacheList list = NULL;
715 SilcIDCacheEntry id_cache = NULL;
716 SilcServerEntry server_entry = NULL;
718 if (silc_idcache_get_all(server->local_list->servers, &list)) {
719 if (silc_idcache_list_first(list, &id_cache)) {
721 server_entry = (SilcServerEntry)id_cache->context;
722 if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry) {
723 if (!silc_idcache_list_next(list, &id_cache))
730 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
732 server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
734 if (!silc_idcache_list_next(list, &id_cache))
738 silc_idcache_list_free(list);
741 if (silc_idcache_get_all(server->global_list->servers, &list)) {
742 if (silc_idcache_list_first(list, &id_cache)) {
744 server_entry = (SilcServerEntry)id_cache->context;
745 if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry) {
746 if (!silc_idcache_list_next(list, &id_cache))
753 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
755 server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
757 if (!silc_idcache_list_next(list, &id_cache))
761 silc_idcache_list_free(list);
765 /* Removes servers that are originated from the `from'. The server
766 entry is deleted in this function. If `remove_clients' is TRUE then
767 all clients originated from the server are removed too, and server
768 signoff is sent. Note that this does not remove the `from'. This
769 also does not remove locally connected servers. */
771 void silc_server_remove_servers_by_server(SilcServer server,
772 SilcServerEntry from,
775 SilcIDCacheList list = NULL;
776 SilcIDCacheEntry id_cache = NULL;
777 SilcServerEntry server_entry = NULL;
779 SILC_LOG_DEBUG(("Removing servers by %s",
780 from->server_name ? from->server_name : "server"));
782 if (silc_idcache_get_all(server->local_list->servers, &list)) {
783 if (silc_idcache_list_first(list, &id_cache)) {
785 server_entry = (SilcServerEntry)id_cache->context;
786 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
787 server_entry->router != from || server_entry == from) {
788 if (!silc_idcache_list_next(list, &id_cache))
794 /* Remove clients owned by this server */
796 silc_server_remove_clients_by_server(server, from, server_entry,
799 /* Remove the server */
800 silc_idlist_del_server(server->local_list, server_entry);
802 if (!silc_idcache_list_next(list, &id_cache))
806 silc_idcache_list_free(list);
809 if (silc_idcache_get_all(server->global_list->servers, &list)) {
810 if (silc_idcache_list_first(list, &id_cache)) {
812 server_entry = (SilcServerEntry)id_cache->context;
813 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
814 server_entry->router != from || server_entry == from) {
815 if (!silc_idcache_list_next(list, &id_cache))
821 /* Remove clients owned by this server */
823 silc_server_remove_clients_by_server(server, from, server_entry,
826 /* Remove the server */
827 silc_idlist_del_server(server->global_list, server_entry);
829 if (!silc_idcache_list_next(list, &id_cache))
833 silc_idcache_list_free(list);
837 /* Removes channels that are from `from. */
839 void silc_server_remove_channels_by_server(SilcServer server,
840 SilcServerEntry from)
842 SilcIDCacheList list = NULL;
843 SilcIDCacheEntry id_cache = NULL;
844 SilcChannelEntry channel = NULL;
846 SILC_LOG_DEBUG(("Removing channels by server"));
848 if (silc_idcache_get_all(server->global_list->channels, &list)) {
849 if (silc_idcache_list_first(list, &id_cache)) {
851 channel = (SilcChannelEntry)id_cache->context;
852 if (channel->router == from)
853 silc_idlist_del_channel(server->global_list, channel);
854 if (!silc_idcache_list_next(list, &id_cache))
858 silc_idcache_list_free(list);
862 /* Updates channels that are from `from' to be originated from `to'. */
864 void silc_server_update_channels_by_server(SilcServer server,
865 SilcServerEntry from,
868 SilcIDCacheList list = NULL;
869 SilcIDCacheEntry id_cache = NULL;
870 SilcChannelEntry channel = NULL;
872 SILC_LOG_DEBUG(("Updating channels by server"));
874 if (silc_idcache_get_all(server->global_list->channels, &list)) {
875 if (silc_idcache_list_first(list, &id_cache)) {
877 channel = (SilcChannelEntry)id_cache->context;
878 if (channel->router == from)
879 channel->router = to;
880 if (!silc_idcache_list_next(list, &id_cache))
884 silc_idcache_list_free(list);
888 /* Checks whether given channel has global users. If it does this returns
889 TRUE and FALSE if there is only locally connected clients on the channel. */
891 bool silc_server_channel_has_global(SilcChannelEntry channel)
893 SilcChannelClientEntry chl;
894 SilcHashTableList htl;
896 silc_hash_table_list(channel->user_list, &htl);
897 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
898 if (chl->client->router) {
899 silc_hash_table_list_reset(&htl);
903 silc_hash_table_list_reset(&htl);
908 /* Checks whether given channel has locally connected users. If it does this
909 returns TRUE and FALSE if there is not one locally connected client. */
911 bool silc_server_channel_has_local(SilcChannelEntry channel)
913 SilcChannelClientEntry chl;
914 SilcHashTableList htl;
916 silc_hash_table_list(channel->user_list, &htl);
917 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
918 if (!chl->client->router) {
919 silc_hash_table_list_reset(&htl);
923 silc_hash_table_list_reset(&htl);
928 /* This function removes the channel and all users on the channel, unless
929 the channel is permanent. In this case the channel is disabled but all
930 users are removed from the channel. Returns TRUE if the channel is
931 destroyed totally, and FALSE if it is permanent and remains. */
933 bool silc_server_channel_delete(SilcServer server,
934 SilcChannelEntry channel)
936 SilcChannelClientEntry chl;
937 SilcHashTableList htl;
938 bool delchan = !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH);
940 if (delchan || server->server_shutdown) {
941 /* Update statistics */
942 if (server->server_type == SILC_ROUTER)
943 server->stat.chanclients -= channel->user_count;
945 /* Totally delete the channel and all users on the channel. The
946 users are deleted automatically in silc_idlist_del_channel. */
947 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
948 if (silc_idlist_del_channel(server->local_list, channel)) {
949 server->stat.my_channels--;
950 if (server->server_type == SILC_ROUTER) {
951 server->stat.channels--;
952 server->stat.cell_channels--;
955 if (silc_idlist_del_channel(server->global_list, channel))
956 if (server->server_type == SILC_ROUTER)
957 server->stat.channels--;
963 /* Channel is permanent, do not remove it, remove only users */
964 channel->disabled = TRUE;
965 silc_hash_table_list(channel->user_list, &htl);
966 while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
967 silc_hash_table_del(chl->client->channels, channel);
968 silc_hash_table_del(channel->user_list, chl->client);
969 channel->user_count--;
971 /* Update statistics */
972 if (SILC_IS_LOCAL(chl->client))
973 server->stat.my_chanclients--;
974 if (server->server_type == SILC_ROUTER) {
975 server->stat.cell_chanclients--;
976 server->stat.chanclients--;
981 silc_hash_table_list_reset(&htl);
983 SILC_LOG_DEBUG(("Channel %s remains", channel->channel_name));
988 /* Returns TRUE if the given client is on the channel. FALSE if not.
989 This works because we assure that the user list on the channel is
990 always in up to date thus we can only check the channel list from
991 `client' which is faster than checking the user list from `channel'. */
993 bool silc_server_client_on_channel(SilcClientEntry client,
994 SilcChannelEntry channel,
995 SilcChannelClientEntry *chl)
997 if (!client || !channel)
1000 return silc_hash_table_find(client->channels, channel, NULL,
1004 /* Checks string for bad characters and returns TRUE if they are found. */
1006 bool silc_server_name_bad_chars(const char *name, SilcUInt32 name_len)
1010 for (i = 0; i < name_len; i++) {
1011 if (!isascii(name[i]))
1013 if (name[i] <= 32) return TRUE;
1014 if (name[i] == ' ') return TRUE;
1015 if (name[i] == '*') return TRUE;
1016 if (name[i] == '?') return TRUE;
1017 if (name[i] == ',') return TRUE;
1023 /* Modifies the `name' if it includes bad characters and returns new
1024 allocated name that does not include bad characters. */
1026 char *silc_server_name_modify_bad(const char *name, SilcUInt32 name_len)
1029 char *newname = strdup(name);
1031 for (i = 0; i < name_len; i++) {
1032 if (!isascii(newname[i])) newname[i] = '_';
1033 if (newname[i] <= 32) newname[i] = '_';
1034 if (newname[i] == ' ') newname[i] = '_';
1035 if (newname[i] == '*') newname[i] = '_';
1036 if (newname[i] == '?') newname[i] = '_';
1037 if (newname[i] == ',') newname[i] = '_';
1043 /* Find number of sockets by IP address indicated by `ip'. Returns 0 if
1044 socket connections with the IP address does not exist. */
1046 SilcUInt32 silc_server_num_sockets_by_ip(SilcServer server, const char *ip,
1047 SilcSocketType type)
1051 for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
1052 if (server->sockets[i] && !SILC_IS_LISTENER(server->sockets[i]) &&
1053 !strcmp(server->sockets[i]->ip, ip) &&
1054 server->sockets[i]->type == type)
1061 /* Find number of sockets by IP address indicated by remote host, indicatd
1062 by `ip' or `hostname', `port', and `type'. Returns 0 if socket connections
1063 does not exist. If `ip' is provided then `hostname' is ignored. */
1065 SilcUInt32 silc_server_num_sockets_by_remote(SilcServer server,
1067 const char *hostname,
1069 SilcSocketType type)
1073 if (!ip && !hostname)
1076 for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
1077 if (server->sockets[i] && !SILC_IS_LISTENER(server->sockets[i]) &&
1078 ((ip && !strcmp(server->sockets[i]->ip, ip)) ||
1079 (hostname && !strcmp(server->sockets[i]->hostname, hostname))) &&
1080 server->sockets[i]->port == port &&
1081 server->sockets[i]->type == type)
1088 /* Finds locally cached public key by the public key received in the SKE.
1089 If we have it locally cached then we trust it and will use it in the
1090 authentication protocol. Returns the locally cached public key or NULL
1091 if we do not find the public key. */
1093 SilcPublicKey silc_server_find_public_key(SilcServer server,
1094 SilcHashTable local_public_keys,
1095 SilcPublicKey remote_public_key)
1097 SilcPublicKey cached_key;
1099 SILC_LOG_DEBUG(("Find remote public key (%d keys in local cache)",
1100 silc_hash_table_count(local_public_keys)));
1102 if (!silc_hash_table_find_ext(local_public_keys, remote_public_key,
1103 (void **)&cached_key, NULL,
1104 silc_hash_public_key, NULL,
1105 silc_hash_public_key_compare, NULL)) {
1106 SILC_LOG_ERROR(("Public key not found"));
1110 SILC_LOG_DEBUG(("Found public key"));
1115 /* This returns the first public key from the table of public keys. This
1116 is used only in cases where single public key exists in the table and
1117 we want to get a pointer to it. For public key tables that has multiple
1118 keys in it the silc_server_find_public_key must be used. */
1120 SilcPublicKey silc_server_get_public_key(SilcServer server,
1121 SilcHashTable local_public_keys)
1123 SilcPublicKey cached_key;
1124 SilcHashTableList htl;
1126 SILC_LOG_DEBUG(("Start"));
1128 assert(silc_hash_table_count(local_public_keys) < 2);
1130 silc_hash_table_list(local_public_keys, &htl);
1131 if (!silc_hash_table_get(&htl, NULL, (void **)&cached_key))
1133 silc_hash_table_list_reset(&htl);
1138 /* Check whether the connection `sock' is allowed to connect to us. This
1139 checks for example whether there is too much connections for this host,
1140 and required version for the host etc. */
1142 bool silc_server_connection_allowed(SilcServer server,
1143 SilcSocketConnection sock,
1144 SilcSocketType type,
1145 SilcServerConfigConnParams *global,
1146 SilcServerConfigConnParams *params,
1149 SilcUInt32 conn_number = (type == SILC_SOCKET_TYPE_CLIENT ?
1150 server->stat.my_clients :
1151 type == SILC_SOCKET_TYPE_SERVER ?
1152 server->stat.my_servers :
1153 server->stat.my_routers);
1154 SilcUInt32 num_sockets, max_hosts, max_per_host;
1155 SilcUInt32 r_protocol_version, l_protocol_version;
1156 SilcUInt32 r_software_version, l_software_version;
1157 char *r_vendor_version = NULL, *l_vendor_version;
1159 SILC_LOG_DEBUG(("Checking whether connection is allowed"));
1163 l_protocol_version =
1164 silc_version_to_num(params && params->version_protocol ?
1165 params->version_protocol :
1166 global->version_protocol);
1167 l_software_version =
1168 silc_version_to_num(params && params->version_software ?
1169 params->version_software :
1170 global->version_software);
1171 l_vendor_version = (params && params->version_software_vendor ?
1172 params->version_software_vendor :
1173 global->version_software_vendor);
1175 if (ske && silc_ske_parse_version(ske, &r_protocol_version, NULL,
1176 &r_software_version, NULL,
1177 &r_vendor_version)) {
1178 sock->version = r_protocol_version;
1180 /* Match protocol version */
1181 if (l_protocol_version && r_protocol_version &&
1182 r_protocol_version < l_protocol_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 protocol version");
1191 /* Math software version */
1192 if (l_software_version && r_software_version &&
1193 r_software_version < l_software_version) {
1194 SILC_LOG_INFO(("Connection %s (%s) is too old version",
1195 sock->hostname, sock->ip));
1196 silc_server_disconnect_remote(server, sock,
1197 SILC_STATUS_ERR_BAD_VERSION,
1198 "You support too old software version");
1202 /* Regex match vendor version */
1203 if (l_vendor_version && r_vendor_version &&
1204 !silc_string_match(l_vendor_version, r_vendor_version)) {
1205 SILC_LOG_INFO(("Connection %s (%s) is unsupported version",
1206 sock->hostname, sock->ip));
1207 silc_server_disconnect_remote(server, sock,
1208 SILC_STATUS_ERR_BAD_VERSION,
1209 "Your software is not supported");
1213 silc_free(r_vendor_version);
1215 /* Check for maximum connections limit */
1217 num_sockets = silc_server_num_sockets_by_ip(server, sock->ip, type);
1218 max_hosts = (params ? params->connections_max : global->connections_max);
1219 max_per_host = (params ? params->connections_max_per_host :
1220 global->connections_max_per_host);
1222 if (max_hosts && conn_number >= max_hosts) {
1223 SILC_LOG_INFO(("Server is full, closing %s (%s) connection",
1224 sock->hostname, sock->ip));
1225 silc_server_disconnect_remote(server, sock,
1226 SILC_STATUS_ERR_RESOURCE_LIMIT,
1227 "Server is full, try again later");
1231 if (num_sockets >= max_per_host) {
1232 SILC_LOG_INFO(("Too many connections from %s (%s), closing connection",
1233 sock->hostname, sock->ip));
1234 silc_server_disconnect_remote(server, sock,
1235 SILC_STATUS_ERR_RESOURCE_LIMIT,
1236 "Too many connections from your host");
1243 /* Checks that client has rights to add or remove channel modes. If any
1244 of the checks fails FALSE is returned. */
1246 bool silc_server_check_cmode_rights(SilcServer server,
1247 SilcChannelEntry channel,
1248 SilcChannelClientEntry client,
1251 bool is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1252 bool is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1254 /* Check whether has rights to change anything */
1255 if (!is_op && !is_fo)
1258 /* Check whether has rights to change everything */
1262 /* Founder implies operator */
1266 /* We know that client is channel operator, check that they are not
1267 changing anything that requires channel founder rights. Rest of the
1268 modes are available automatically for channel operator. */
1270 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1271 if (is_op && !is_fo)
1274 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1275 if (is_op && !is_fo)
1280 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1281 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
1282 if (is_op && !is_fo)
1286 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1287 if (is_op && !is_fo)
1292 if (mode & SILC_CHANNEL_MODE_CIPHER) {
1293 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
1294 if (is_op && !is_fo)
1298 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1299 if (is_op && !is_fo)
1304 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1305 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
1306 if (is_op && !is_fo)
1310 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1311 if (is_op && !is_fo)
1316 if (mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1317 if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS)) {
1318 if (is_op && !is_fo)
1322 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1323 if (is_op && !is_fo)
1328 if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1329 if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS)) {
1330 if (is_op && !is_fo)
1334 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1335 if (is_op && !is_fo)
1343 /* Check that the client has rights to change its user mode. Returns
1344 FALSE if setting some mode is not allowed. */
1346 bool silc_server_check_umode_rights(SilcServer server,
1347 SilcClientEntry client,
1350 bool server_op = FALSE, router_op = FALSE;
1352 if (mode & SILC_UMODE_SERVER_OPERATOR) {
1353 /* Cannot set server operator mode (must use OPER command) */
1354 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR))
1357 /* Remove the server operator rights */
1358 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
1362 if (mode & SILC_UMODE_ROUTER_OPERATOR) {
1363 /* Cannot set router operator mode (must use SILCOPER command) */
1364 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR))
1367 /* Remove the router operator rights */
1368 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
1373 SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR);
1375 SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR);
1380 /* This function is used to send the notify packets and motd to the
1381 incoming client connection. */
1383 void silc_server_send_connect_notifys(SilcServer server,
1384 SilcSocketConnection sock,
1385 SilcClientEntry client)
1387 SilcIDListData idata = (SilcIDListData)client;
1389 SILC_LOG_DEBUG(("Send welcome notifys"));
1391 /* Send some nice info to the client */
1392 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1393 ("Welcome to the SILC Network %s",
1395 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1396 ("Your host is %s, running version %s",
1397 server->server_name, server_version));
1399 if (server->server_type == SILC_ROUTER) {
1400 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1401 ("There are %d clients, %d servers and %d "
1402 "routers in SILC Network",
1403 server->stat.clients, server->stat.servers + 1,
1404 server->stat.routers));
1406 if (server->stat.clients && server->stat.servers + 1)
1407 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1408 ("There are %d clients, %d servers and %d "
1409 "routers in SILC Network",
1410 server->stat.clients, server->stat.servers + 1,
1411 (server->standalone ? 0 :
1412 !server->stat.routers ? 1 :
1413 server->stat.routers)));
1416 if (server->stat.cell_clients && server->stat.cell_servers + 1)
1417 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1418 ("There are %d clients on %d server in our cell",
1419 server->stat.cell_clients,
1420 server->stat.cell_servers + 1));
1421 if (server->server_type == SILC_ROUTER) {
1422 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1423 ("I have %d clients, %d channels, %d servers and "
1425 server->stat.my_clients,
1426 server->stat.my_channels,
1427 server->stat.my_servers,
1428 server->stat.my_routers));
1430 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1431 ("I have %d clients and %d channels formed",
1432 server->stat.my_clients,
1433 server->stat.my_channels));
1436 if (server->stat.server_ops || server->stat.router_ops)
1437 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1438 ("There are %d server operators and %d router "
1440 server->stat.server_ops,
1441 server->stat.router_ops));
1442 if (server->stat.my_router_ops + server->stat.my_server_ops)
1443 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1444 ("I have %d operators online",
1445 server->stat.my_router_ops +
1446 server->stat.my_server_ops));
1448 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1449 ("Your connection is secured with %s cipher, "
1450 "key length %d bits",
1451 idata->send_key->cipher->name,
1452 idata->send_key->cipher->key_len));
1453 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1454 ("Your current nickname is %s",
1458 silc_server_send_motd(server, sock);
1461 /* Kill the client indicated by `remote_client' sending KILLED notify
1462 to the client, to all channels client has joined and to primary
1463 router if needed. The killed client is also removed from all channels. */
1465 void silc_server_kill_client(SilcServer server,
1466 SilcClientEntry remote_client,
1467 const char *comment,
1469 SilcIdType killer_id_type)
1471 SilcBuffer killed, killer;
1473 SILC_LOG_DEBUG(("Killing client %s",
1474 silc_id_render(remote_client->id, SILC_ID_CLIENT)));
1476 /* Send the KILL notify packets. First send it to the channel, then
1477 to our primary router and then directly to the client who is being
1478 killed right now. */
1480 killed = silc_id_payload_encode(remote_client->id, SILC_ID_CLIENT);
1481 killer = silc_id_payload_encode(killer_id, killer_id_type);
1483 /* Send KILLED notify to the channels. It is not sent to the client
1484 as it will be sent differently destined directly to the client and not
1486 silc_server_send_notify_on_channels(server, remote_client,
1487 remote_client, SILC_NOTIFY_TYPE_KILLED,
1488 3, killed->data, killed->len,
1489 comment, comment ? strlen(comment) : 0,
1490 killer->data, killer->len);
1492 /* Send KILLED notify to primary route */
1493 silc_server_send_notify_killed(server, SILC_PRIMARY_ROUTE(server),
1494 SILC_BROADCAST(server), remote_client->id,
1495 comment, killer_id, killer_id_type);
1497 /* Send KILLED notify to the client directly */
1498 if (remote_client->connection || remote_client->router)
1499 silc_server_send_notify_killed(server, remote_client->connection ?
1500 remote_client->connection :
1501 remote_client->router->connection, FALSE,
1502 remote_client->id, comment,
1503 killer_id, killer_id_type);
1505 /* Remove the client from all channels. This generates new keys to the
1506 channels as well. */
1507 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
1510 /* Remove the client entry, If it is locally connected then we will also
1511 disconnect the client here */
1512 if (remote_client->connection) {
1513 /* Remove locally conneted client */
1514 SilcSocketConnection sock = remote_client->connection;
1515 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
1516 silc_server_close_connection(server, sock);
1518 /* Update statistics */
1519 server->stat.clients--;
1520 if (server->stat.cell_clients)
1521 server->stat.cell_clients--;
1522 SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
1523 SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
1525 if (SILC_IS_LOCAL(remote_client)) {
1526 server->stat.my_clients--;
1527 silc_schedule_task_del_by_context(server->schedule, remote_client);
1528 silc_idlist_del_data(remote_client);
1531 /* Remove remote client */
1532 silc_idlist_del_data(remote_client);
1533 if (!silc_idlist_del_client(server->global_list, remote_client)) {
1534 /* Remove this client from watcher list if it is */
1535 silc_server_del_from_watcher_list(server, remote_client);
1536 silc_idlist_del_client(server->local_list, remote_client);
1540 silc_buffer_free(killer);
1541 silc_buffer_free(killed);
1546 SilcClientEntry client;
1547 SilcNotifyType notify;
1548 const char *new_nick;
1549 } WatcherNotifyContext;
1552 silc_server_check_watcher_list_foreach(void *key, void *context,
1555 WatcherNotifyContext *notify = user_context;
1556 SilcClientEntry entry = context;
1557 SilcSocketConnection sock;
1559 if (entry == notify->client)
1562 sock = silc_server_get_client_route(notify->server, NULL, 0, entry->id,
1565 SILC_LOG_DEBUG(("Sending WATCH notify to %s",
1566 silc_id_render(entry->id, SILC_ID_CLIENT)));
1568 /* Send the WATCH notify */
1569 silc_server_send_notify_watch(notify->server, sock, entry,
1571 notify->new_nick ? notify->new_nick :
1572 (const char *)notify->client->nickname,
1577 /* This function checks whether the `client' nickname is being watched
1578 by someone, and notifies the watcher of the notify change of notify
1579 type indicated by `notify'. */
1581 bool silc_server_check_watcher_list(SilcServer server,
1582 SilcClientEntry client,
1583 const char *new_nick,
1584 SilcNotifyType notify)
1586 unsigned char hash[16];
1587 WatcherNotifyContext n;
1589 SILC_LOG_DEBUG(("Checking watcher list %s",
1590 client->nickname ? client->nickname : (unsigned char *)""));
1592 /* If the watching is rejected by the client do nothing */
1593 if (client->mode & SILC_UMODE_REJECT_WATCHING)
1596 /* Make hash from the nick, or take it from Client ID */
1597 if (client->nickname) {
1599 memset(nick, 0, sizeof(nick));
1600 silc_to_lower(client->nickname, nick, sizeof(nick) - 1);
1601 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
1603 memset(hash, 0, sizeof(hash));
1604 memcpy(hash, client->id->hash, sizeof(client->id->hash));
1609 n.new_nick = new_nick;
1612 /* Send notify to all watchers */
1613 silc_hash_table_find_foreach(server->watcher_list, hash,
1614 silc_server_check_watcher_list_foreach, &n);
1619 /* Remove the `client' from watcher list. After calling this the `client'
1620 is not watching any nicknames. */
1622 bool silc_server_del_from_watcher_list(SilcServer server,
1623 SilcClientEntry client)
1625 SilcHashTableList htl;
1627 SilcClientEntry entry;
1630 silc_hash_table_list(server->watcher_list, &htl);
1631 while (silc_hash_table_get(&htl, &key, (void **)&entry)) {
1632 if (entry == client) {
1633 silc_hash_table_del_by_context(server->watcher_list, key, client);
1636 SILC_LOG_DEBUG(("Removing %s from WATCH list",
1637 silc_id_render(client->id, SILC_ID_CLIENT)));
1639 /* Now check whether there still exists entries with this key, if not
1640 then free the key to not leak memory. */
1641 if (!silc_hash_table_find(server->watcher_list, key, NULL, NULL))
1647 silc_hash_table_list_reset(&htl);
1652 /* Force the client indicated by `chl' to change the channel user mode
1653 on channel indicated by `channel' to `forced_mode'. */
1655 bool silc_server_force_cumode_change(SilcServer server,
1656 SilcSocketConnection sock,
1657 SilcChannelEntry channel,
1658 SilcChannelClientEntry chl,
1659 SilcUInt32 forced_mode)
1661 SilcBuffer idp1, idp2;
1662 unsigned char cumode[4];
1664 SILC_LOG_DEBUG(("Enforcing sender to change mode"));
1667 silc_server_send_notify_cumode(server, sock, FALSE, channel, forced_mode,
1668 server->id, SILC_ID_SERVER,
1669 chl->client->id, NULL);
1671 idp1 = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1672 idp2 = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
1673 SILC_PUT32_MSB(forced_mode, cumode);
1674 silc_server_send_notify_to_channel(server, sock, channel, FALSE,
1675 SILC_NOTIFY_TYPE_CUMODE_CHANGE,
1676 3, idp1->data, idp1->len,
1677 cumode, sizeof(cumode),
1678 idp2->data, idp2->len);
1679 silc_buffer_free(idp1);
1680 silc_buffer_free(idp2);
1685 /* Find active socket connection by the IP address and port indicated by
1686 `ip' and `port', and socket connection type of `type'. */
1688 SilcSocketConnection
1689 silc_server_find_socket_by_host(SilcServer server,
1690 SilcSocketType type,
1691 const char *ip, SilcUInt16 port)
1695 for (i = 0; i < server->config->param.connections_max; i++) {
1696 if (!server->sockets[i])
1698 if (!strcmp(server->sockets[i]->ip, ip) &&
1699 (!port || server->sockets[i]->port == port) &&
1700 server->sockets[i]->type == type)
1701 return server->sockets[i];