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_ROUTER &&
59 silc_hash_table_count(channel->user_list) < 2) {
60 if (silc_hash_table_find(channels, channel, NULL, NULL))
61 silc_hash_table_del(channels, channel);
62 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
63 silc_server_channel_delete(server, channel);
67 silc_hash_table_del(client->channels, channel);
68 silc_hash_table_del(channel->user_list, chl->client);
69 channel->user_count--;
71 /* If there is no global users on the channel anymore mark the channel
72 as local channel. Do not check if the removed client is local client. */
73 if (server->server_type != SILC_ROUTER && channel->global_users &&
74 chl->client->router && !silc_server_channel_has_global(channel))
75 channel->global_users = FALSE;
79 /* Update statistics */
80 if (SILC_IS_LOCAL(client))
81 server->stat.my_chanclients--;
82 if (server->server_type == SILC_ROUTER) {
83 server->stat.cell_chanclients--;
84 server->stat.chanclients--;
87 /* If there is not at least one local user on the channel then we don't
88 need the channel entry anymore, we can remove it safely, unless the
89 channel is permanent channel */
90 if (server->server_type != SILC_ROUTER &&
91 !silc_server_channel_has_local(channel)) {
92 if (silc_hash_table_find(channels, channel, NULL, NULL))
93 silc_hash_table_del(channels, channel);
94 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
95 silc_server_channel_delete(server, channel);
99 /* Mark other local clients to the table of clients whom will receive
100 the SERVER_SIGNOFF notify. */
101 silc_hash_table_list(channel->user_list, &htl2);
102 while (silc_hash_table_get(&htl2, NULL, (void **)&chl2)) {
103 SilcClientEntry c = chl2->client;
107 /* Add client to table, if it's not from the signoff server */
108 if (c->router != server_entry &&
109 !silc_hash_table_find(clients, c, NULL, NULL))
110 silc_hash_table_add(clients, c, c);
112 silc_hash_table_list_reset(&htl2);
114 /* Add the channel to the the channels list to regenerate the
116 if (!silc_hash_table_find(channels, channel, NULL, NULL))
117 silc_hash_table_add(channels, channel, channel);
119 silc_hash_table_list_reset(&htl);
122 /* This function removes all client entries that are originated from
123 `router' and are owned by `entry'. `router' and `entry' can be same
124 too. If `server_signoff' is TRUE then SERVER_SIGNOFF notify is
125 distributed to our local clients. */
127 bool silc_server_remove_clients_by_server(SilcServer server,
128 SilcServerEntry router,
129 SilcServerEntry entry,
132 SilcIDCacheList list = NULL;
133 SilcIDCacheEntry id_cache = NULL;
134 SilcClientEntry client = NULL;
136 unsigned char **argv = NULL;
137 SilcUInt32 *argv_lens = NULL, *argv_types = NULL, argc = 0;
138 SilcHashTableList htl;
139 SilcChannelEntry channel;
140 SilcHashTable channels, clients;
143 if (!(entry->data.status & SILC_IDLIST_STATUS_REGISTERED))
146 SILC_LOG_DEBUG(("Removing clients by %s",
147 entry->server_name ? entry->server_name : "server"));
152 /* Allocate the hash table that holds the channels that require
153 channel key re-generation after we've removed this server's clients
154 from the channels. */
155 channels = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL,
157 clients = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL,
160 if (server_signoff) {
161 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
162 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
163 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) * (argc + 1));
164 argv_types = silc_realloc(argv_types, sizeof(*argv_types) * (argc + 1));
165 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
166 memcpy(argv[argc], idp->data, idp->len);
167 argv_lens[argc] = idp->len;
168 argv_types[argc] = argc + 1;
170 silc_buffer_free(idp);
173 if (silc_idcache_get_all(server->local_list->clients, &list)) {
174 if (silc_idcache_list_first(list, &id_cache)) {
176 client = (SilcClientEntry)id_cache->context;
178 /* If client is not registered, is not originated from `router'
179 or is not owned by `entry', skip it. */
180 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
181 client->router != router ||
182 (router != entry && !SILC_ID_COMPARE(client->id, entry->id,
183 client->id->ip.data_len))) {
184 if (!silc_idcache_list_next(list, &id_cache))
190 if (server_signoff) {
191 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
192 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
193 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
195 argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
197 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
198 memcpy(argv[argc], idp->data, idp->len);
199 argv_lens[argc] = idp->len;
200 argv_types[argc] = argc + 1;
202 silc_buffer_free(idp);
205 /* Update statistics */
206 server->stat.clients--;
207 if (server->stat.cell_clients)
208 server->stat.cell_clients--;
209 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
210 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
212 silc_server_remove_clients_channels(server, entry, clients,
214 silc_server_del_from_watcher_list(server, client);
216 /* Remove the client entry */
217 if (!server_signoff) {
218 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
219 id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
221 silc_idlist_del_client(server->local_list, client);
224 if (!silc_idcache_list_next(list, &id_cache))
228 silc_idcache_list_free(list);
231 if (silc_idcache_get_all(server->global_list->clients, &list)) {
233 if (silc_idcache_list_first(list, &id_cache)) {
235 client = (SilcClientEntry)id_cache->context;
237 /* If client is not registered, is not originated from `router'
238 or is not owned by `entry', skip it. */
239 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
240 client->router != router ||
241 (router != entry && !SILC_ID_COMPARE(client->id, entry->id,
242 client->id->ip.data_len))) {
243 if (!silc_idcache_list_next(list, &id_cache))
249 if (server_signoff) {
250 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
251 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
252 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
254 argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
256 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
257 memcpy(argv[argc], idp->data, idp->len);
258 argv_lens[argc] = idp->len;
259 argv_types[argc] = argc + 1;
261 silc_buffer_free(idp);
264 /* Update statistics */
265 server->stat.clients--;
266 if (server->stat.cell_clients)
267 server->stat.cell_clients--;
268 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
269 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
271 silc_server_remove_clients_channels(server, entry, clients,
273 silc_server_del_from_watcher_list(server, client);
275 /* Remove the client entry */
276 if (!server_signoff) {
277 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
278 id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
280 silc_idlist_del_client(server->global_list, client);
283 if (!silc_idcache_list_next(list, &id_cache))
287 silc_idcache_list_free(list);
290 /* Send the SERVER_SIGNOFF notify */
291 if (server_signoff) {
292 SilcBuffer args, not;
294 SILC_LOG_DEBUG(("Sending SERVER_SIGNOFF for %s with %d clients",
295 silc_id_render(entry->id, SILC_ID_SERVER), argc - 1));
297 /* Send SERVER_SIGNOFF notify to our primary router */
298 if (server->router != entry) {
299 args = silc_argument_payload_encode(1, argv, argv_lens,
301 silc_server_send_notify_args(server, SILC_PRIMARY_ROUTE(server),
302 SILC_BROADCAST(server),
303 SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
305 silc_buffer_free(args);
308 /* Send to local clients. We also send the list of client ID's that
309 is to be removed for those servers that would like to use that list. */
310 args = silc_argument_payload_encode(argc, argv, argv_lens,
312 not = silc_notify_payload_encode_args(SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
314 silc_server_packet_send_clients(server, clients,
315 SILC_PACKET_NOTIFY, 0, FALSE,
316 not->data, not->len, FALSE);
318 silc_buffer_free(args);
319 silc_buffer_free(not);
320 for (i = 0; i < argc; i++)
323 silc_free(argv_lens);
324 silc_free(argv_types);
325 silc_hash_table_free(clients);
328 /* We must now re-generate the channel key for all channels that had
329 this server's client(s) on the channel. As they left the channel we
330 must re-generate the channel key. */
331 silc_hash_table_list(channels, &htl);
332 while (silc_hash_table_get(&htl, NULL, (void **)&channel)) {
333 if (!silc_server_create_channel_key(server, channel, 0)) {
334 silc_hash_table_list_reset(&htl);
335 silc_hash_table_free(channels);
339 /* Do not send the channel key if private channel key mode is set */
340 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY)
343 silc_server_send_channel_key(server, NULL, channel,
344 server->server_type == SILC_ROUTER ?
345 FALSE : !server->standalone);
347 silc_hash_table_list_reset(&htl);
348 silc_hash_table_free(channels);
353 static SilcServerEntry
354 silc_server_update_clients_by_real_server(SilcServer server,
355 SilcServerEntry from,
356 SilcClientEntry client,
358 SilcIDCacheEntry client_cache)
360 SilcServerEntry server_entry;
361 SilcIDCacheEntry id_cache = NULL;
362 SilcIDCacheList list;
364 if (!silc_idcache_get_all(server->local_list->servers, &list))
367 if (silc_idcache_list_first(list, &id_cache)) {
369 server_entry = (SilcServerEntry)id_cache->context;
370 if (server_entry != from &&
371 SILC_ID_COMPARE(server_entry->id, client->id,
372 client->id->ip.data_len)) {
373 SILC_LOG_DEBUG(("Found (local) %s",
374 silc_id_render(server_entry->id, SILC_ID_SERVER)));
376 if (!server_entry->data.send_key && server_entry->router) {
377 SILC_LOG_DEBUG(("Server not locally connected, use its router"));
378 /* If the client is not marked as local then move it to local list
379 since the server is local. */
381 SILC_LOG_DEBUG(("Moving client to local list"));
382 silc_idcache_add(server->local_list->clients, client_cache->name,
383 client_cache->id, client_cache->context,
384 client_cache->expire, NULL);
385 silc_idcache_del_by_context(server->global_list->clients, client);
387 server_entry = server_entry->router;
389 /* If the client is not marked as local then move it to local list
390 since the server is local. */
391 if (server_entry->server_type != SILC_BACKUP_ROUTER && !local) {
392 SILC_LOG_DEBUG(("Moving client to local list"));
393 silc_idcache_add(server->local_list->clients, client_cache->name,
394 client_cache->id, client_cache->context,
395 client_cache->expire, NULL);
396 silc_idcache_del_by_context(server->global_list->clients, client);
400 silc_idcache_list_free(list);
404 if (!silc_idcache_list_next(list, &id_cache))
409 silc_idcache_list_free(list);
411 if (!silc_idcache_get_all(server->global_list->servers, &list))
414 if (silc_idcache_list_first(list, &id_cache)) {
416 server_entry = (SilcServerEntry)id_cache->context;
417 if (server_entry != from &&
418 SILC_ID_COMPARE(server_entry->id, client->id,
419 client->id->ip.data_len)) {
420 SILC_LOG_DEBUG(("Found (global) %s",
421 silc_id_render(server_entry->id, SILC_ID_SERVER)));
423 if (!server_entry->data.send_key && server_entry->router) {
424 SILC_LOG_DEBUG(("Server not locally connected, use its router"));
425 /* If the client is marked as local then move it to global list
426 since the server is global. */
428 SILC_LOG_DEBUG(("Moving client to global list"));
429 silc_idcache_add(server->global_list->clients, client_cache->name,
430 client_cache->id, client_cache->context,
431 client_cache->expire, NULL);
432 silc_idcache_del_by_context(server->local_list->clients, client);
434 server_entry = server_entry->router;
436 /* If the client is marked as local then move it to global list
437 since the server is global. */
438 if (server_entry->server_type != SILC_BACKUP_ROUTER && local) {
439 SILC_LOG_DEBUG(("Moving client to global list"));
440 silc_idcache_add(server->global_list->clients, client_cache->name,
441 client_cache->id, client_cache->context,
442 client_cache->expire, NULL);
443 silc_idcache_del_by_context(server->local_list->clients, client);
447 silc_idcache_list_free(list);
451 if (!silc_idcache_list_next(list, &id_cache))
456 silc_idcache_list_free(list);
461 /* Updates the clients that are originated from the `from' to be originated
462 from the `to'. If the `resolve_real_server' is TRUE then this will
463 attempt to figure out which clients really are originated from the
464 `from' and which are originated from a server that we have connection
465 to, when we've acting as backup router. If it is FALSE the `to' will
466 be the new source. */
468 void silc_server_update_clients_by_server(SilcServer server,
469 SilcServerEntry from,
471 bool resolve_real_server)
473 SilcIDCacheList list = NULL;
474 SilcIDCacheEntry id_cache = NULL;
475 SilcClientEntry client = NULL;
479 if (silc_idcache_get_all(server->global_list->clients, &list)) {
480 if (silc_idcache_list_first(list, &id_cache)) {
482 client = (SilcClientEntry)id_cache->context;
484 /* If entry is disabled skip it. If entry is local to us, do not
485 switch it to anyone else, it is ours so skip it. */
486 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
487 SILC_IS_LOCAL(client)) {
488 if (!silc_idcache_list_next(list, &id_cache))
494 SILC_LOG_DEBUG(("Client %s",
495 silc_id_render(client->id, SILC_ID_CLIENT)));
497 SILC_LOG_DEBUG(("Client->router %s",
498 silc_id_render(client->router->id, SILC_ID_SERVER)));
501 if (client->router == from) {
502 if (resolve_real_server) {
504 silc_server_update_clients_by_real_server(server, from, client,
506 if (!client->router) {
507 if (server->server_type == SILC_ROUTER)
508 client->router = from;
517 /* All are changed */
522 SILC_LOG_DEBUG(("Client changed to %s",
523 silc_id_render(client->router->id, SILC_ID_CLIENT)));
525 if (!silc_idcache_list_next(list, &id_cache))
529 silc_idcache_list_free(list);
533 if (silc_idcache_get_all(server->local_list->clients, &list)) {
534 if (silc_idcache_list_first(list, &id_cache)) {
536 client = (SilcClientEntry)id_cache->context;
538 /* If entry is disabled skip it. If entry is local to us, do not
539 switch it to anyone else, it is ours so skip it. */
540 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
541 SILC_IS_LOCAL(client)) {
542 if (!silc_idcache_list_next(list, &id_cache))
548 SILC_LOG_DEBUG(("Client %s",
549 silc_id_render(client->id, SILC_ID_CLIENT)));
551 SILC_LOG_DEBUG(("Client->router %s",
552 silc_id_render(client->router->id, SILC_ID_SERVER)));
555 if (client->router == from) {
556 if (resolve_real_server) {
558 silc_server_update_clients_by_real_server(server, from, client,
561 client->router = from;
567 /* All are changed */
572 SILC_LOG_DEBUG(("Client changed to %s",
573 silc_id_render(client->router->id, SILC_ID_CLIENT)));
575 if (!silc_idcache_list_next(list, &id_cache))
579 silc_idcache_list_free(list);
583 /* Updates servers that are from `from' to be originated from `to'. This
584 will also update the server's connection to `to's connection. */
586 void silc_server_update_servers_by_server(SilcServer server,
587 SilcServerEntry from,
590 SilcIDCacheList list = NULL;
591 SilcIDCacheEntry id_cache = NULL;
592 SilcServerEntry server_entry = NULL;
594 SILC_LOG_DEBUG(("Updating servers"));
596 if (silc_idcache_get_all(server->local_list->servers, &list)) {
597 if (silc_idcache_list_first(list, &id_cache)) {
599 server_entry = (SilcServerEntry)id_cache->context;
601 /* If entry is local to us, do not switch it to any anyone else,
603 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
604 server_entry == from) {
605 if (!silc_idcache_list_next(list, &id_cache))
611 /* If we are standalone router, any server that is not directly
612 connected to cannot exist anymore. If we are not standalone
613 we update it correctly. */
614 if (server->server_type == SILC_ROUTER && server->standalone) {
615 silc_server_backup_del(server, server_entry);
616 silc_server_backup_replaced_del(server, server_entry);
617 silc_idlist_del_data(server_entry);
618 silc_idlist_del_server(server->local_list, server_entry);
619 server->stat.servers--;
620 server->stat.cell_servers--;
622 /* XXX if we are not standalone, do a check from local config
623 whether this server is in our cell, but not connected to
624 us (in which case we must remove it). */
626 if (server_entry->router == from) {
627 SILC_LOG_DEBUG(("Updating server (local) %s",
628 server_entry->server_name ?
629 server_entry->server_name : ""));
630 server_entry->router = to;
631 server_entry->connection = to->connection;
635 if (!silc_idcache_list_next(list, &id_cache))
639 silc_idcache_list_free(list);
642 if (silc_idcache_get_all(server->global_list->servers, &list)) {
643 if (silc_idcache_list_first(list, &id_cache)) {
645 server_entry = (SilcServerEntry)id_cache->context;
647 /* If entry is local to us, do not switch it to anyone else,
649 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
650 server_entry == from) {
651 if (!silc_idcache_list_next(list, &id_cache))
657 /* If we are standalone router, any server that is not directly
658 connected to cannot exist anymore. If we are not standalone
659 we update it correctly. */
660 if (server->server_type == SILC_ROUTER && server->standalone) {
661 silc_server_backup_del(server, server_entry);
662 silc_server_backup_replaced_del(server, server_entry);
663 silc_idlist_del_data(server_entry);
664 silc_idlist_del_server(server->global_list, server_entry);
665 server->stat.servers--;
666 server->stat.cell_servers--;
668 /* XXX if we are not standalone, do a check from local config
669 whether this server is in our cell, but not connected to
670 us (in which case we must remove it). */
672 if (server_entry->router == from) {
673 SILC_LOG_DEBUG(("Updating server (global) %s",
674 server_entry->server_name ?
675 server_entry->server_name : ""));
676 server_entry->router = to;
677 server_entry->connection = to->connection;
681 if (!silc_idcache_list_next(list, &id_cache))
685 silc_idcache_list_free(list);
690 /* Toggles the enabled/disabled status of local server connections. Packets
691 can be sent to the servers when `toggle_enabled' is TRUE and will be
692 dropped if `toggle_enabled' is FALSE, after this function is called. */
694 void silc_server_local_servers_toggle_enabled(SilcServer server,
697 SilcIDCacheList list = NULL;
698 SilcIDCacheEntry id_cache = NULL;
699 SilcServerEntry server_entry = NULL;
701 if (silc_idcache_get_all(server->local_list->servers, &list)) {
702 if (silc_idcache_list_first(list, &id_cache)) {
704 server_entry = (SilcServerEntry)id_cache->context;
705 if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry) {
706 if (!silc_idcache_list_next(list, &id_cache))
713 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
715 server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
717 if (!silc_idcache_list_next(list, &id_cache))
721 silc_idcache_list_free(list);
724 if (silc_idcache_get_all(server->global_list->servers, &list)) {
725 if (silc_idcache_list_first(list, &id_cache)) {
727 server_entry = (SilcServerEntry)id_cache->context;
728 if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry) {
729 if (!silc_idcache_list_next(list, &id_cache))
736 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
738 server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
740 if (!silc_idcache_list_next(list, &id_cache))
744 silc_idcache_list_free(list);
748 /* Removes servers that are originated from the `from'. The server
749 entry is deleted in this function. If `remove_clients' is TRUE then
750 all clients originated from the server are removed too, and server
751 signoff is sent. Note that this does not remove the `from'. This
752 also does not remove locally connected servers. */
754 void silc_server_remove_servers_by_server(SilcServer server,
755 SilcServerEntry from,
758 SilcIDCacheList list = NULL;
759 SilcIDCacheEntry id_cache = NULL;
760 SilcServerEntry server_entry = NULL;
762 SILC_LOG_DEBUG(("Removing servers by %s",
763 from->server_name ? from->server_name : "server"));
765 if (silc_idcache_get_all(server->local_list->servers, &list)) {
766 if (silc_idcache_list_first(list, &id_cache)) {
768 server_entry = (SilcServerEntry)id_cache->context;
769 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
770 server_entry->router != from || server_entry == from) {
771 if (!silc_idcache_list_next(list, &id_cache))
777 /* Remove clients owned by this server */
779 silc_server_remove_clients_by_server(server, from, server_entry,
782 /* Remove the server */
783 silc_idlist_del_server(server->local_list, server_entry);
785 if (!silc_idcache_list_next(list, &id_cache))
789 silc_idcache_list_free(list);
792 if (silc_idcache_get_all(server->global_list->servers, &list)) {
793 if (silc_idcache_list_first(list, &id_cache)) {
795 server_entry = (SilcServerEntry)id_cache->context;
796 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
797 server_entry->router != from || server_entry == from) {
798 if (!silc_idcache_list_next(list, &id_cache))
804 /* Remove clients owned by this server */
806 silc_server_remove_clients_by_server(server, from, server_entry,
809 /* Remove the server */
810 silc_idlist_del_server(server->global_list, server_entry);
812 if (!silc_idcache_list_next(list, &id_cache))
816 silc_idcache_list_free(list);
820 /* Removes channels that are from `from. */
822 void silc_server_remove_channels_by_server(SilcServer server,
823 SilcServerEntry from)
825 SilcIDCacheList list = NULL;
826 SilcIDCacheEntry id_cache = NULL;
827 SilcChannelEntry channel = NULL;
829 SILC_LOG_DEBUG(("Removing channels by server"));
831 if (silc_idcache_get_all(server->global_list->channels, &list)) {
832 if (silc_idcache_list_first(list, &id_cache)) {
834 channel = (SilcChannelEntry)id_cache->context;
835 if (channel->router == from)
836 silc_idlist_del_channel(server->global_list, channel);
837 if (!silc_idcache_list_next(list, &id_cache))
841 silc_idcache_list_free(list);
845 /* Updates channels that are from `from' to be originated from `to'. */
847 void silc_server_update_channels_by_server(SilcServer server,
848 SilcServerEntry from,
851 SilcIDCacheList list = NULL;
852 SilcIDCacheEntry id_cache = NULL;
853 SilcChannelEntry channel = NULL;
855 SILC_LOG_DEBUG(("Updating channels by server"));
857 if (silc_idcache_get_all(server->global_list->channels, &list)) {
858 if (silc_idcache_list_first(list, &id_cache)) {
860 channel = (SilcChannelEntry)id_cache->context;
861 if (channel->router == from)
862 channel->router = to;
863 if (!silc_idcache_list_next(list, &id_cache))
867 silc_idcache_list_free(list);
871 /* Checks whether given channel has global users. If it does this returns
872 TRUE and FALSE if there is only locally connected clients on the channel. */
874 bool silc_server_channel_has_global(SilcChannelEntry channel)
876 SilcChannelClientEntry chl;
877 SilcHashTableList htl;
879 silc_hash_table_list(channel->user_list, &htl);
880 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
881 if (chl->client->router) {
882 silc_hash_table_list_reset(&htl);
886 silc_hash_table_list_reset(&htl);
891 /* Checks whether given channel has locally connected users. If it does this
892 returns TRUE and FALSE if there is not one locally connected client. */
894 bool silc_server_channel_has_local(SilcChannelEntry channel)
896 SilcChannelClientEntry chl;
897 SilcHashTableList htl;
899 silc_hash_table_list(channel->user_list, &htl);
900 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
901 if (!chl->client->router) {
902 silc_hash_table_list_reset(&htl);
906 silc_hash_table_list_reset(&htl);
911 /* This function removes the channel and all users on the channel, unless
912 the channel is permanent. In this case the channel is disabled but all
913 users are removed from the channel. Returns TRUE if the channel is
914 destroyed totally, and FALSE if it is permanent and remains. */
916 bool silc_server_channel_delete(SilcServer server,
917 SilcChannelEntry channel)
919 SilcChannelClientEntry chl;
920 SilcHashTableList htl;
921 bool delchan = !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH);
924 /* Update statistics */
925 if (server->server_type == SILC_ROUTER)
926 server->stat.chanclients -= channel->user_count;
928 /* Totally delete the channel and all users on the channel. The
929 users are deleted automatically in silc_idlist_del_channel. */
930 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
931 if (silc_idlist_del_channel(server->local_list, channel)) {
932 server->stat.my_channels--;
933 if (server->server_type == SILC_ROUTER) {
934 server->stat.channels--;
935 server->stat.cell_channels--;
938 if (silc_idlist_del_channel(server->global_list, channel))
939 if (server->server_type == SILC_ROUTER)
940 server->stat.channels--;
946 /* Channel is permanent, do not remove it, remove only users */
947 channel->disabled = TRUE;
948 silc_hash_table_list(channel->user_list, &htl);
949 while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
950 silc_hash_table_del(chl->client->channels, channel);
951 silc_hash_table_del(channel->user_list, chl->client);
952 channel->user_count--;
954 /* Update statistics */
955 if (SILC_IS_LOCAL(chl->client))
956 server->stat.my_chanclients--;
957 if (server->server_type == SILC_ROUTER) {
958 server->stat.cell_chanclients--;
959 server->stat.chanclients--;
964 silc_hash_table_list_reset(&htl);
966 SILC_LOG_DEBUG(("Channel %s remains", channel->channel_name));
971 /* Returns TRUE if the given client is on the channel. FALSE if not.
972 This works because we assure that the user list on the channel is
973 always in up to date thus we can only check the channel list from
974 `client' which is faster than checking the user list from `channel'. */
976 bool silc_server_client_on_channel(SilcClientEntry client,
977 SilcChannelEntry channel,
978 SilcChannelClientEntry *chl)
980 if (!client || !channel)
983 return silc_hash_table_find(client->channels, channel, NULL,
987 /* Checks string for bad characters and returns TRUE if they are found. */
989 bool silc_server_name_bad_chars(const char *name, SilcUInt32 name_len)
993 for (i = 0; i < name_len; i++) {
994 if (!isascii(name[i]))
996 if (name[i] <= 32) return TRUE;
997 if (name[i] == ' ') return TRUE;
998 if (name[i] == '*') return TRUE;
999 if (name[i] == '?') return TRUE;
1000 if (name[i] == ',') return TRUE;
1006 /* Modifies the `name' if it includes bad characters and returns new
1007 allocated name that does not include bad characters. */
1009 char *silc_server_name_modify_bad(const char *name, SilcUInt32 name_len)
1012 char *newname = strdup(name);
1014 for (i = 0; i < name_len; i++) {
1015 if (!isascii(newname[i])) newname[i] = '_';
1016 if (newname[i] <= 32) newname[i] = '_';
1017 if (newname[i] == ' ') newname[i] = '_';
1018 if (newname[i] == '*') newname[i] = '_';
1019 if (newname[i] == '?') newname[i] = '_';
1020 if (newname[i] == ',') newname[i] = '_';
1026 /* Find number of sockets by IP address indicated by `ip'. Returns 0 if
1027 socket connections with the IP address does not exist. */
1029 SilcUInt32 silc_server_num_sockets_by_ip(SilcServer server, const char *ip,
1030 SilcSocketType type)
1034 for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
1035 if (server->sockets[i] && !strcmp(server->sockets[i]->ip, ip) &&
1036 server->sockets[i]->type == type)
1043 /* Find number of sockets by IP address indicated by remote host, indicatd
1044 by `ip' or `hostname', `port', and `type'. Returns 0 if socket connections
1045 does not exist. If `ip' is provided then `hostname' is ignored. */
1047 SilcUInt32 silc_server_num_sockets_by_remote(SilcServer server,
1049 const char *hostname,
1051 SilcSocketType type)
1055 if (!ip && !hostname)
1058 for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
1059 if (server->sockets[i] &&
1060 ((ip && !strcmp(server->sockets[i]->ip, ip)) ||
1061 (hostname && !strcmp(server->sockets[i]->hostname, hostname))) &&
1062 server->sockets[i]->port == port &&
1063 server->sockets[i]->type == type)
1070 /* Finds locally cached public key by the public key received in the SKE.
1071 If we have it locally cached then we trust it and will use it in the
1072 authentication protocol. Returns the locally cached public key or NULL
1073 if we do not find the public key. */
1075 SilcPublicKey silc_server_find_public_key(SilcServer server,
1076 SilcHashTable local_public_keys,
1077 SilcPublicKey remote_public_key)
1079 SilcPublicKey cached_key;
1081 SILC_LOG_DEBUG(("Find remote public key (%d keys in local cache)",
1082 silc_hash_table_count(local_public_keys)));
1084 if (!silc_hash_table_find_ext(local_public_keys, remote_public_key,
1085 (void **)&cached_key, NULL,
1086 silc_hash_public_key, NULL,
1087 silc_hash_public_key_compare, NULL)) {
1088 SILC_LOG_ERROR(("Public key not found"));
1092 SILC_LOG_DEBUG(("Found public key"));
1097 /* This returns the first public key from the table of public keys. This
1098 is used only in cases where single public key exists in the table and
1099 we want to get a pointer to it. For public key tables that has multiple
1100 keys in it the silc_server_find_public_key must be used. */
1102 SilcPublicKey silc_server_get_public_key(SilcServer server,
1103 SilcHashTable local_public_keys)
1105 SilcPublicKey cached_key;
1106 SilcHashTableList htl;
1108 SILC_LOG_DEBUG(("Start"));
1110 assert(silc_hash_table_count(local_public_keys) < 2);
1112 silc_hash_table_list(local_public_keys, &htl);
1113 if (!silc_hash_table_get(&htl, NULL, (void **)&cached_key))
1115 silc_hash_table_list_reset(&htl);
1120 /* Check whether the connection `sock' is allowed to connect to us. This
1121 checks for example whether there is too much connections for this host,
1122 and required version for the host etc. */
1124 bool silc_server_connection_allowed(SilcServer server,
1125 SilcSocketConnection sock,
1126 SilcSocketType type,
1127 SilcServerConfigConnParams *global,
1128 SilcServerConfigConnParams *params,
1131 SilcUInt32 conn_number = (type == SILC_SOCKET_TYPE_CLIENT ?
1132 server->stat.my_clients :
1133 type == SILC_SOCKET_TYPE_SERVER ?
1134 server->stat.my_servers :
1135 server->stat.my_routers);
1136 SilcUInt32 num_sockets, max_hosts, max_per_host;
1137 SilcUInt32 r_protocol_version, l_protocol_version;
1138 SilcUInt32 r_software_version, l_software_version;
1139 char *r_vendor_version = NULL, *l_vendor_version;
1141 SILC_LOG_DEBUG(("Checking whether connection is allowed"));
1145 l_protocol_version =
1146 silc_version_to_num(params && params->version_protocol ?
1147 params->version_protocol :
1148 global->version_protocol);
1149 l_software_version =
1150 silc_version_to_num(params && params->version_software ?
1151 params->version_software :
1152 global->version_software);
1153 l_vendor_version = (params && params->version_software_vendor ?
1154 params->version_software_vendor :
1155 global->version_software_vendor);
1157 if (ske && silc_ske_parse_version(ske, &r_protocol_version, NULL,
1158 &r_software_version, NULL,
1159 &r_vendor_version)) {
1160 sock->version = r_protocol_version;
1162 /* Match protocol version */
1163 if (l_protocol_version && r_protocol_version &&
1164 r_protocol_version < l_protocol_version) {
1165 SILC_LOG_INFO(("Connection %s (%s) is too old version",
1166 sock->hostname, sock->ip));
1167 silc_server_disconnect_remote(server, sock,
1168 SILC_STATUS_ERR_BAD_VERSION,
1169 "You support too old protocol version");
1173 /* Math software version */
1174 if (l_software_version && r_software_version &&
1175 r_software_version < l_software_version) {
1176 SILC_LOG_INFO(("Connection %s (%s) is too old version",
1177 sock->hostname, sock->ip));
1178 silc_server_disconnect_remote(server, sock,
1179 SILC_STATUS_ERR_BAD_VERSION,
1180 "You support too old software version");
1184 /* Regex match vendor version */
1185 if (l_vendor_version && r_vendor_version &&
1186 !silc_string_match(l_vendor_version, r_vendor_version)) {
1187 SILC_LOG_INFO(("Connection %s (%s) is unsupported version",
1188 sock->hostname, sock->ip));
1189 silc_server_disconnect_remote(server, sock,
1190 SILC_STATUS_ERR_BAD_VERSION,
1191 "Your software is not supported");
1195 silc_free(r_vendor_version);
1197 /* Check for maximum connections limit */
1199 num_sockets = silc_server_num_sockets_by_ip(server, sock->ip, type);
1200 max_hosts = (params ? params->connections_max : global->connections_max);
1201 max_per_host = (params ? params->connections_max_per_host :
1202 global->connections_max_per_host);
1204 if (max_hosts && conn_number >= max_hosts) {
1205 SILC_LOG_INFO(("Server is full, closing %s (%s) connection",
1206 sock->hostname, sock->ip));
1207 silc_server_disconnect_remote(server, sock,
1208 SILC_STATUS_ERR_RESOURCE_LIMIT,
1209 "Server is full, try again later");
1213 if (num_sockets >= max_per_host) {
1214 SILC_LOG_INFO(("Too many connections from %s (%s), closing connection",
1215 sock->hostname, sock->ip));
1216 silc_server_disconnect_remote(server, sock,
1217 SILC_STATUS_ERR_RESOURCE_LIMIT,
1218 "Too many connections from your host");
1225 /* Checks that client has rights to add or remove channel modes. If any
1226 of the checks fails FALSE is returned. */
1228 bool silc_server_check_cmode_rights(SilcServer server,
1229 SilcChannelEntry channel,
1230 SilcChannelClientEntry client,
1233 bool is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1234 bool is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1236 /* Check whether has rights to change anything */
1237 if (!is_op && !is_fo)
1240 /* Check whether has rights to change everything */
1244 /* Founder implies operator */
1248 /* We know that client is channel operator, check that they are not
1249 changing anything that requires channel founder rights. Rest of the
1250 modes are available automatically for channel operator. */
1252 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1253 if (is_op && !is_fo)
1256 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1257 if (is_op && !is_fo)
1262 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1263 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
1264 if (is_op && !is_fo)
1268 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1269 if (is_op && !is_fo)
1274 if (mode & SILC_CHANNEL_MODE_CIPHER) {
1275 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
1276 if (is_op && !is_fo)
1280 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1281 if (is_op && !is_fo)
1286 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1287 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
1288 if (is_op && !is_fo)
1292 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1293 if (is_op && !is_fo)
1298 if (mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1299 if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS)) {
1300 if (is_op && !is_fo)
1304 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1305 if (is_op && !is_fo)
1310 if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1311 if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS)) {
1312 if (is_op && !is_fo)
1316 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1317 if (is_op && !is_fo)
1325 /* Check that the client has rights to change its user mode. Returns
1326 FALSE if setting some mode is not allowed. */
1328 bool silc_server_check_umode_rights(SilcServer server,
1329 SilcClientEntry client,
1332 bool server_op = FALSE, router_op = FALSE;
1334 if (mode & SILC_UMODE_SERVER_OPERATOR) {
1335 /* Cannot set server operator mode (must use OPER command) */
1336 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR))
1339 /* Remove the server operator rights */
1340 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
1344 if (mode & SILC_UMODE_ROUTER_OPERATOR) {
1345 /* Cannot set router operator mode (must use SILCOPER command) */
1346 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR))
1349 /* Remove the router operator rights */
1350 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
1355 SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR);
1357 SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR);
1362 /* This function is used to send the notify packets and motd to the
1363 incoming client connection. */
1365 void silc_server_send_connect_notifys(SilcServer server,
1366 SilcSocketConnection sock,
1367 SilcClientEntry client)
1369 SilcIDListData idata = (SilcIDListData)client;
1371 SILC_LOG_DEBUG(("Send welcome notifys"));
1373 /* Send some nice info to the client */
1374 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1375 ("Welcome to the SILC Network %s",
1377 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1378 ("Your host is %s, running version %s",
1379 server->server_name, server_version));
1381 if (server->server_type == SILC_ROUTER) {
1382 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1383 ("There are %d clients, %d servers and %d "
1384 "routers in SILC Network",
1385 server->stat.clients, server->stat.servers + 1,
1386 server->stat.routers));
1388 if (server->stat.clients && server->stat.servers + 1)
1389 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1390 ("There are %d clients, %d servers and %d "
1391 "routers in SILC Network",
1392 server->stat.clients, server->stat.servers + 1,
1393 (server->standalone ? 0 :
1394 !server->stat.routers ? 1 :
1395 server->stat.routers)));
1398 if (server->stat.cell_clients && server->stat.cell_servers + 1)
1399 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1400 ("There are %d clients on %d server in our cell",
1401 server->stat.cell_clients,
1402 server->stat.cell_servers + 1));
1403 if (server->server_type == SILC_ROUTER) {
1404 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1405 ("I have %d clients, %d channels, %d servers and "
1407 server->stat.my_clients,
1408 server->stat.my_channels,
1409 server->stat.my_servers,
1410 server->stat.my_routers));
1412 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1413 ("I have %d clients and %d channels formed",
1414 server->stat.my_clients,
1415 server->stat.my_channels));
1418 if (server->stat.server_ops || server->stat.router_ops)
1419 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1420 ("There are %d server operators and %d router "
1422 server->stat.server_ops,
1423 server->stat.router_ops));
1424 if (server->stat.my_router_ops + server->stat.my_server_ops)
1425 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1426 ("I have %d operators online",
1427 server->stat.my_router_ops +
1428 server->stat.my_server_ops));
1430 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1431 ("Your connection is secured with %s cipher, "
1432 "key length %d bits",
1433 idata->send_key->cipher->name,
1434 idata->send_key->cipher->key_len));
1435 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1436 ("Your current nickname is %s",
1440 silc_server_send_motd(server, sock);
1443 /* Kill the client indicated by `remote_client' sending KILLED notify
1444 to the client, to all channels client has joined and to primary
1445 router if needed. The killed client is also removed from all channels. */
1447 void silc_server_kill_client(SilcServer server,
1448 SilcClientEntry remote_client,
1449 const char *comment,
1451 SilcIdType killer_id_type)
1453 SilcBuffer killed, killer;
1455 SILC_LOG_DEBUG(("Killing client %s",
1456 silc_id_render(remote_client->id, SILC_ID_CLIENT)));
1458 /* Send the KILL notify packets. First send it to the channel, then
1459 to our primary router and then directly to the client who is being
1460 killed right now. */
1462 killed = silc_id_payload_encode(remote_client->id, SILC_ID_CLIENT);
1463 killer = silc_id_payload_encode(killer_id, killer_id_type);
1465 /* Send KILLED notify to the channels. It is not sent to the client
1466 as it will be sent differently destined directly to the client and not
1468 silc_server_send_notify_on_channels(server, remote_client,
1469 remote_client, SILC_NOTIFY_TYPE_KILLED,
1470 3, killed->data, killed->len,
1471 comment, comment ? strlen(comment) : 0,
1472 killer->data, killer->len);
1474 /* Send KILLED notify to primary route */
1475 silc_server_send_notify_killed(server, SILC_PRIMARY_ROUTE(server),
1476 SILC_BROADCAST(server), remote_client->id,
1477 comment, killer_id, killer_id_type);
1479 /* Send KILLED notify to the client directly */
1480 if (remote_client->connection || remote_client->router)
1481 silc_server_send_notify_killed(server, remote_client->connection ?
1482 remote_client->connection :
1483 remote_client->router->connection, FALSE,
1484 remote_client->id, comment,
1485 killer_id, killer_id_type);
1487 /* Remove the client from all channels. This generates new keys to the
1488 channels as well. */
1489 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
1492 /* Remove the client entry, If it is locally connected then we will also
1493 disconnect the client here */
1494 if (remote_client->connection) {
1495 /* Remove locally conneted client */
1496 SilcSocketConnection sock = remote_client->connection;
1497 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
1498 silc_server_close_connection(server, sock);
1500 /* Update statistics */
1501 server->stat.clients--;
1502 if (server->stat.cell_clients)
1503 server->stat.cell_clients--;
1504 SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
1505 SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
1507 if (SILC_IS_LOCAL(remote_client)) {
1508 server->stat.my_clients--;
1509 silc_schedule_task_del_by_context(server->schedule, remote_client);
1510 silc_idlist_del_data(remote_client);
1513 /* Remove remote client */
1514 if (!silc_idlist_del_client(server->global_list, remote_client)) {
1515 /* Remove this client from watcher list if it is */
1516 silc_server_del_from_watcher_list(server, remote_client);
1517 silc_idlist_del_client(server->local_list, remote_client);
1521 silc_buffer_free(killer);
1522 silc_buffer_free(killed);
1527 SilcClientEntry client;
1528 SilcNotifyType notify;
1529 const char *new_nick;
1530 } WatcherNotifyContext;
1533 silc_server_check_watcher_list_foreach(void *key, void *context,
1536 WatcherNotifyContext *notify = user_context;
1537 SilcClientEntry entry = context;
1538 SilcSocketConnection sock;
1540 if (entry == notify->client)
1543 sock = silc_server_get_client_route(notify->server, NULL, 0, entry->id,
1546 SILC_LOG_DEBUG(("Sending WATCH notify to %s",
1547 silc_id_render(entry->id, SILC_ID_CLIENT)));
1549 /* Send the WATCH notify */
1550 silc_server_send_notify_watch(notify->server, sock, entry,
1552 notify->new_nick ? notify->new_nick :
1553 (const char *)notify->client->nickname,
1558 /* This function checks whether the `client' nickname is being watched
1559 by someone, and notifies the watcher of the notify change of notify
1560 type indicated by `notify'. */
1562 bool silc_server_check_watcher_list(SilcServer server,
1563 SilcClientEntry client,
1564 const char *new_nick,
1565 SilcNotifyType notify)
1567 unsigned char hash[16];
1568 WatcherNotifyContext n;
1570 SILC_LOG_DEBUG(("Checking watcher list %s",
1571 client->nickname ? client->nickname : (unsigned char *)""));
1573 /* If the watching is rejected by the client do nothing */
1574 if (client->mode & SILC_UMODE_REJECT_WATCHING)
1577 /* Make hash from the nick, or take it from Client ID */
1578 if (client->nickname) {
1580 memset(nick, 0, sizeof(nick));
1581 silc_to_lower(client->nickname, nick, sizeof(nick) - 1);
1582 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
1584 memset(hash, 0, sizeof(hash));
1585 memcpy(hash, client->id->hash, sizeof(client->id->hash));
1590 n.new_nick = new_nick;
1593 /* Send notify to all watchers */
1594 silc_hash_table_find_foreach(server->watcher_list, hash,
1595 silc_server_check_watcher_list_foreach, &n);
1600 /* Remove the `client' from watcher list. After calling this the `client'
1601 is not watching any nicknames. */
1603 bool silc_server_del_from_watcher_list(SilcServer server,
1604 SilcClientEntry client)
1606 SilcHashTableList htl;
1608 SilcClientEntry entry;
1611 silc_hash_table_list(server->watcher_list, &htl);
1612 while (silc_hash_table_get(&htl, &key, (void **)&entry)) {
1613 if (entry == client) {
1614 silc_hash_table_del_by_context(server->watcher_list, key, client);
1617 SILC_LOG_DEBUG(("Removing %s from WATCH list",
1618 silc_id_render(client->id, SILC_ID_CLIENT)));
1620 /* Now check whether there still exists entries with this key, if not
1621 then free the key to not leak memory. */
1622 if (!silc_hash_table_find(server->watcher_list, key, NULL, NULL))
1628 silc_hash_table_list_reset(&htl);
1633 /* Force the client indicated by `chl' to change the channel user mode
1634 on channel indicated by `channel' to `forced_mode'. */
1636 bool silc_server_force_cumode_change(SilcServer server,
1637 SilcSocketConnection sock,
1638 SilcChannelEntry channel,
1639 SilcChannelClientEntry chl,
1640 SilcUInt32 forced_mode)
1642 SilcBuffer idp1, idp2;
1643 unsigned char cumode[4];
1645 SILC_LOG_DEBUG(("Enforcing sender to change mode"));
1648 silc_server_send_notify_cumode(server, sock, FALSE, channel, forced_mode,
1649 server->id, SILC_ID_SERVER,
1650 chl->client->id, NULL);
1652 idp1 = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1653 idp2 = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
1654 SILC_PUT32_MSB(forced_mode, cumode);
1655 silc_server_send_notify_to_channel(server, sock, channel, FALSE,
1656 SILC_NOTIFY_TYPE_CUMODE_CHANGE,
1657 3, idp1->data, idp1->len,
1658 cumode, sizeof(cumode),
1659 idp2->data, idp2->len);
1660 silc_buffer_free(idp1);
1661 silc_buffer_free(idp2);
1666 /* Find active socket connection by the IP address and port indicated by
1667 `ip' and `port', and socket connection type of `type'. */
1669 SilcSocketConnection
1670 silc_server_find_socket_by_host(SilcServer server,
1671 SilcSocketType type,
1672 const char *ip, SilcUInt16 port)
1676 for (i = 0; i < server->config->param.connections_max; i++) {
1677 if (!server->sockets[i])
1679 if (!strcmp(server->sockets[i]->ip, ip) &&
1680 (!port || server->sockets[i]->port == port) &&
1681 server->sockets[i]->type == type)
1682 return server->sockets[i];