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 !SILC_ID_COMPARE(client->id, entry->id, client->id->ip.data_len)) {
183 if (!silc_idcache_list_next(list, &id_cache))
189 if (server_signoff) {
190 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
191 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
192 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
194 argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
196 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
197 memcpy(argv[argc], idp->data, idp->len);
198 argv_lens[argc] = idp->len;
199 argv_types[argc] = argc + 1;
201 silc_buffer_free(idp);
204 /* Update statistics */
205 server->stat.clients--;
206 if (server->stat.cell_clients)
207 server->stat.cell_clients--;
208 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
209 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
211 silc_server_remove_clients_channels(server, entry, clients,
213 silc_server_del_from_watcher_list(server, client);
215 /* Remove the client entry */
216 if (!server_signoff) {
217 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
218 id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
220 silc_idlist_del_client(server->local_list, client);
223 if (!silc_idcache_list_next(list, &id_cache))
227 silc_idcache_list_free(list);
230 if (silc_idcache_get_all(server->global_list->clients, &list)) {
232 if (silc_idcache_list_first(list, &id_cache)) {
234 client = (SilcClientEntry)id_cache->context;
236 /* If client is not registered, is not originated from `router'
237 or is not owned by `entry', skip it. */
238 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
239 client->router != router ||
240 !SILC_ID_COMPARE(client->id, entry->id, client->id->ip.data_len)) {
241 if (!silc_idcache_list_next(list, &id_cache))
247 if (server_signoff) {
248 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
249 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
250 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
252 argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
254 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
255 memcpy(argv[argc], idp->data, idp->len);
256 argv_lens[argc] = idp->len;
257 argv_types[argc] = argc + 1;
259 silc_buffer_free(idp);
262 /* Update statistics */
263 server->stat.clients--;
264 if (server->stat.cell_clients)
265 server->stat.cell_clients--;
266 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
267 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
269 silc_server_remove_clients_channels(server, entry, clients,
271 silc_server_del_from_watcher_list(server, client);
273 /* Remove the client entry */
274 if (!server_signoff) {
275 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
276 id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
278 silc_idlist_del_client(server->global_list, client);
281 if (!silc_idcache_list_next(list, &id_cache))
285 silc_idcache_list_free(list);
288 /* Send the SERVER_SIGNOFF notify */
289 if (server_signoff) {
290 SilcBuffer args, not;
292 SILC_LOG_DEBUG(("Sending SERVER_SIGNOFF for %s with %d clients",
293 silc_id_render(entry->id, SILC_ID_SERVER), argc - 1));
295 /* Send SERVER_SIGNOFF notify to our primary router */
296 if (server->router != entry) {
297 args = silc_argument_payload_encode(1, argv, argv_lens,
299 silc_server_send_notify_args(server, SILC_PRIMARY_ROUTE(server),
300 SILC_BROADCAST(server),
301 SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
303 silc_buffer_free(args);
306 /* Send to local clients. We also send the list of client ID's that
307 is to be removed for those servers that would like to use that list. */
308 args = silc_argument_payload_encode(argc, argv, argv_lens,
310 not = silc_notify_payload_encode_args(SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
312 silc_server_packet_send_clients(server, clients,
313 SILC_PACKET_NOTIFY, 0, FALSE,
314 not->data, not->len, FALSE);
316 silc_buffer_free(args);
317 silc_buffer_free(not);
318 for (i = 0; i < argc; i++)
321 silc_free(argv_lens);
322 silc_free(argv_types);
323 silc_hash_table_free(clients);
326 /* We must now re-generate the channel key for all channels that had
327 this server's client(s) on the channel. As they left the channel we
328 must re-generate the channel key. */
329 silc_hash_table_list(channels, &htl);
330 while (silc_hash_table_get(&htl, NULL, (void **)&channel)) {
331 if (!silc_server_create_channel_key(server, channel, 0)) {
332 silc_hash_table_list_reset(&htl);
333 silc_hash_table_free(channels);
337 /* Do not send the channel key if private channel key mode is set */
338 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY)
341 silc_server_send_channel_key(server, NULL, channel,
342 server->server_type == SILC_ROUTER ?
343 FALSE : !server->standalone);
345 silc_hash_table_list_reset(&htl);
346 silc_hash_table_free(channels);
351 static SilcServerEntry
352 silc_server_update_clients_by_real_server(SilcServer server,
353 SilcServerEntry from,
354 SilcClientEntry client,
356 SilcIDCacheEntry client_cache)
358 SilcServerEntry server_entry;
359 SilcIDCacheEntry id_cache = NULL;
360 SilcIDCacheList list;
362 if (!silc_idcache_get_all(server->local_list->servers, &list))
365 if (silc_idcache_list_first(list, &id_cache)) {
367 server_entry = (SilcServerEntry)id_cache->context;
368 if (server_entry != from &&
369 SILC_ID_COMPARE(server_entry->id, client->id,
370 client->id->ip.data_len)) {
371 SILC_LOG_DEBUG(("Found (local) %s",
372 silc_id_render(server_entry->id, SILC_ID_SERVER)));
374 if (!server_entry->data.send_key && server_entry->router) {
375 SILC_LOG_DEBUG(("Server not locally connected, use its router"));
376 /* If the client is not marked as local then move it to local list
377 since the server is local. */
379 SILC_LOG_DEBUG(("Moving client to local list"));
380 silc_idcache_add(server->local_list->clients, client_cache->name,
381 client_cache->id, client_cache->context,
382 client_cache->expire, NULL);
383 silc_idcache_del_by_context(server->global_list->clients, client);
385 server_entry = server_entry->router;
387 /* If the client is not marked as local then move it to local list
388 since the server is local. */
389 if (server_entry->server_type != SILC_BACKUP_ROUTER && !local) {
390 SILC_LOG_DEBUG(("Moving client to local list"));
391 silc_idcache_add(server->local_list->clients, client_cache->name,
392 client_cache->id, client_cache->context,
393 client_cache->expire, NULL);
394 silc_idcache_del_by_context(server->global_list->clients, client);
398 silc_idcache_list_free(list);
402 if (!silc_idcache_list_next(list, &id_cache))
407 silc_idcache_list_free(list);
409 if (!silc_idcache_get_all(server->global_list->servers, &list))
412 if (silc_idcache_list_first(list, &id_cache)) {
414 server_entry = (SilcServerEntry)id_cache->context;
415 if (server_entry != from &&
416 SILC_ID_COMPARE(server_entry->id, client->id,
417 client->id->ip.data_len)) {
418 SILC_LOG_DEBUG(("Found (global) %s",
419 silc_id_render(server_entry->id, SILC_ID_SERVER)));
421 if (!server_entry->data.send_key && server_entry->router) {
422 SILC_LOG_DEBUG(("Server not locally connected, use its router"));
423 /* If the client is marked as local then move it to global list
424 since the server is global. */
426 SILC_LOG_DEBUG(("Moving client to global list"));
427 silc_idcache_add(server->global_list->clients, client_cache->name,
428 client_cache->id, client_cache->context,
429 client_cache->expire, NULL);
430 silc_idcache_del_by_context(server->local_list->clients, client);
432 server_entry = server_entry->router;
434 /* If the client is marked as local then move it to global list
435 since the server is global. */
436 if (server_entry->server_type != SILC_BACKUP_ROUTER && local) {
437 SILC_LOG_DEBUG(("Moving client to global list"));
438 silc_idcache_add(server->global_list->clients, client_cache->name,
439 client_cache->id, client_cache->context,
440 client_cache->expire, NULL);
441 silc_idcache_del_by_context(server->local_list->clients, client);
445 silc_idcache_list_free(list);
449 if (!silc_idcache_list_next(list, &id_cache))
454 silc_idcache_list_free(list);
459 /* Updates the clients that are originated from the `from' to be originated
460 from the `to'. If the `resolve_real_server' is TRUE then this will
461 attempt to figure out which clients really are originated from the
462 `from' and which are originated from a server that we have connection
463 to, when we've acting as backup router. If it is FALSE the `to' will
464 be the new source. This function also removes the clients that are
465 *really* originated from `from' if `remove_from' is TRUE. These are
466 clients that the `from' owns, and not just clients that are behind
467 the `from'. If `from' is NULL then all non-local clients are switched
470 void silc_server_update_clients_by_server(SilcServer server,
471 SilcServerEntry from,
473 bool resolve_real_server,
476 SilcIDCacheList list = NULL;
477 SilcIDCacheEntry id_cache = NULL;
478 SilcClientEntry client = NULL;
482 SILC_LOG_DEBUG(("Updating %s", silc_id_render(from->id,
485 SILC_LOG_DEBUG(("to %s", silc_id_render(to->id,
489 if (silc_idcache_get_all(server->global_list->clients, &list)) {
490 if (silc_idcache_list_first(list, &id_cache)) {
492 client = (SilcClientEntry)id_cache->context;
494 /* If entry is disabled skip it. If entry is local to us, do not
495 switch it to anyone else, it is ours so skip it. */
496 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
497 SILC_IS_LOCAL(client)) {
498 if (!silc_idcache_list_next(list, &id_cache))
504 SILC_LOG_DEBUG(("Client (global) %s",
505 silc_id_render(client->id, SILC_ID_CLIENT)));
507 SILC_LOG_DEBUG(("Client->router (global) %s",
508 silc_id_render(client->router->id, SILC_ID_SERVER)));
511 if (client->router == from) {
512 /* Skip clients that are *really* owned by the `from' */
513 if (remove_from && SILC_ID_COMPARE(from->id, client->id,
514 client->id->ip.data_len)) {
515 SILC_LOG_DEBUG(("Found really owned client, skip it"));
516 if (!silc_idcache_list_next(list, &id_cache))
522 if (resolve_real_server) {
524 silc_server_update_clients_by_real_server(server, from, client,
526 if (!client->router) {
527 if (server->server_type == SILC_ROUTER)
528 client->router = from;
537 /* All are changed */
542 SILC_LOG_DEBUG(("Client changed to %s",
543 silc_id_render(client->router->id, SILC_ID_CLIENT)));
545 if (!silc_idcache_list_next(list, &id_cache))
549 silc_idcache_list_free(list);
553 if (silc_idcache_get_all(server->local_list->clients, &list)) {
554 if (silc_idcache_list_first(list, &id_cache)) {
556 client = (SilcClientEntry)id_cache->context;
558 /* If entry is disabled skip it. If entry is local to us, do not
559 switch it to anyone else, it is ours so skip it. */
560 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
561 SILC_IS_LOCAL(client)) {
562 if (!silc_idcache_list_next(list, &id_cache))
568 SILC_LOG_DEBUG(("Client (local) %s",
569 silc_id_render(client->id, SILC_ID_CLIENT)));
571 SILC_LOG_DEBUG(("Client->router (local) %s",
572 silc_id_render(client->router->id, SILC_ID_SERVER)));
575 if (client->router == from) {
576 /* Skip clients that are *really* owned by the `from' */
577 if (remove_from && SILC_ID_COMPARE(from->id, client->id,
578 client->id->ip.data_len)) {
579 SILC_LOG_DEBUG(("Found really owned client, skip it"));
580 if (!silc_idcache_list_next(list, &id_cache))
586 if (resolve_real_server) {
588 silc_server_update_clients_by_real_server(server, from, client,
591 client->router = from;
597 /* All are changed */
602 SILC_LOG_DEBUG(("Client changed to %s",
603 silc_id_render(client->router->id, SILC_ID_CLIENT)));
605 if (!silc_idcache_list_next(list, &id_cache))
609 silc_idcache_list_free(list);
613 /* Now remove the clients that are still marked as orignated from the
614 `from'. These are the clients that really was owned by the `from' and
615 not just exist behind the `from'. */
616 silc_server_remove_clients_by_server(server, from, from, TRUE);
619 /* Updates servers that are from `from' to be originated from `to'. This
620 will also update the server's connection to `to's connection. */
622 void silc_server_update_servers_by_server(SilcServer server,
623 SilcServerEntry from,
626 SilcIDCacheList list = NULL;
627 SilcIDCacheEntry id_cache = NULL;
628 SilcServerEntry server_entry = NULL;
630 SILC_LOG_DEBUG(("Updating servers"));
632 if (silc_idcache_get_all(server->local_list->servers, &list)) {
633 if (silc_idcache_list_first(list, &id_cache)) {
635 server_entry = (SilcServerEntry)id_cache->context;
637 /* If entry is local to us, do not switch it to any anyone else,
639 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
640 server_entry == from) {
641 if (!silc_idcache_list_next(list, &id_cache))
647 /* If we are standalone router, any server that is not directly
648 connected to cannot exist anymore. If we are not standalone
649 we update it correctly. */
650 if (server->server_type == SILC_ROUTER && server->standalone) {
651 silc_server_backup_del(server, server_entry);
652 silc_server_backup_replaced_del(server, server_entry);
653 silc_idlist_del_data(server_entry);
654 silc_idlist_del_server(server->local_list, server_entry);
655 server->stat.servers--;
656 server->stat.cell_servers--;
658 /* XXX if we are not standalone, do a check from local config
659 whether this server is in our cell, but not connected to
660 us (in which case we must remove it). */
662 if (server_entry->router == from) {
663 SILC_LOG_DEBUG(("Updating server (local) %s",
664 server_entry->server_name ?
665 server_entry->server_name : ""));
666 server_entry->router = to;
667 server_entry->connection = to->connection;
671 if (!silc_idcache_list_next(list, &id_cache))
675 silc_idcache_list_free(list);
678 if (silc_idcache_get_all(server->global_list->servers, &list)) {
679 if (silc_idcache_list_first(list, &id_cache)) {
681 server_entry = (SilcServerEntry)id_cache->context;
683 /* If entry is local to us, do not switch it to anyone else,
685 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
686 server_entry == from) {
687 if (!silc_idcache_list_next(list, &id_cache))
693 /* If we are standalone router, any server that is not directly
694 connected to cannot exist anymore. If we are not standalone
695 we update it correctly. */
696 if (server->server_type == SILC_ROUTER && server->standalone) {
697 silc_server_backup_del(server, server_entry);
698 silc_server_backup_replaced_del(server, server_entry);
699 silc_idlist_del_data(server_entry);
700 silc_idlist_del_server(server->global_list, server_entry);
701 server->stat.servers--;
702 server->stat.cell_servers--;
704 /* XXX if we are not standalone, do a check from local config
705 whether this server is in our cell, but not connected to
706 us (in which case we must remove it). */
708 if (server_entry->router == from) {
709 SILC_LOG_DEBUG(("Updating server (global) %s",
710 server_entry->server_name ?
711 server_entry->server_name : ""));
712 server_entry->router = to;
713 server_entry->connection = to->connection;
717 if (!silc_idcache_list_next(list, &id_cache))
721 silc_idcache_list_free(list);
726 /* Toggles the enabled/disabled status of local server connections. Packets
727 can be sent to the servers when `toggle_enabled' is TRUE and will be
728 dropped if `toggle_enabled' is FALSE, after this function is called. */
730 void silc_server_local_servers_toggle_enabled(SilcServer server,
733 SilcIDCacheList list = NULL;
734 SilcIDCacheEntry id_cache = NULL;
735 SilcServerEntry server_entry = NULL;
737 if (silc_idcache_get_all(server->local_list->servers, &list)) {
738 if (silc_idcache_list_first(list, &id_cache)) {
740 server_entry = (SilcServerEntry)id_cache->context;
741 if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry) {
742 if (!silc_idcache_list_next(list, &id_cache))
749 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
751 server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
753 if (!silc_idcache_list_next(list, &id_cache))
757 silc_idcache_list_free(list);
760 if (silc_idcache_get_all(server->global_list->servers, &list)) {
761 if (silc_idcache_list_first(list, &id_cache)) {
763 server_entry = (SilcServerEntry)id_cache->context;
764 if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry) {
765 if (!silc_idcache_list_next(list, &id_cache))
772 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
774 server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
776 if (!silc_idcache_list_next(list, &id_cache))
780 silc_idcache_list_free(list);
784 /* Removes servers that are originated from the `from'. The server
785 entry is deleted in this function. If `remove_clients' is TRUE then
786 all clients originated from the server are removed too, and server
787 signoff is sent. Note that this does not remove the `from'. This
788 also does not remove locally connected servers. */
790 void silc_server_remove_servers_by_server(SilcServer server,
791 SilcServerEntry from,
794 SilcIDCacheList list = NULL;
795 SilcIDCacheEntry id_cache = NULL;
796 SilcServerEntry server_entry = NULL;
798 SILC_LOG_DEBUG(("Removing servers by %s",
799 from->server_name ? from->server_name : "server"));
801 if (silc_idcache_get_all(server->local_list->servers, &list)) {
802 if (silc_idcache_list_first(list, &id_cache)) {
804 server_entry = (SilcServerEntry)id_cache->context;
805 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
806 server_entry->router != from || server_entry == from) {
807 if (!silc_idcache_list_next(list, &id_cache))
813 /* Remove clients owned by this server */
815 silc_server_remove_clients_by_server(server, from, server_entry,
818 /* Remove the server */
819 silc_idlist_del_server(server->local_list, server_entry);
821 if (!silc_idcache_list_next(list, &id_cache))
825 silc_idcache_list_free(list);
828 if (silc_idcache_get_all(server->global_list->servers, &list)) {
829 if (silc_idcache_list_first(list, &id_cache)) {
831 server_entry = (SilcServerEntry)id_cache->context;
832 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
833 server_entry->router != from || server_entry == from) {
834 if (!silc_idcache_list_next(list, &id_cache))
840 /* Remove clients owned by this server */
842 silc_server_remove_clients_by_server(server, from, server_entry,
845 /* Remove the server */
846 silc_idlist_del_server(server->global_list, server_entry);
848 if (!silc_idcache_list_next(list, &id_cache))
852 silc_idcache_list_free(list);
856 /* Removes channels that are from `from. */
858 void silc_server_remove_channels_by_server(SilcServer server,
859 SilcServerEntry from)
861 SilcIDCacheList list = NULL;
862 SilcIDCacheEntry id_cache = NULL;
863 SilcChannelEntry channel = NULL;
865 SILC_LOG_DEBUG(("Removing channels by server"));
867 if (silc_idcache_get_all(server->global_list->channels, &list)) {
868 if (silc_idcache_list_first(list, &id_cache)) {
870 channel = (SilcChannelEntry)id_cache->context;
871 if (channel->router == from)
872 silc_idlist_del_channel(server->global_list, channel);
873 if (!silc_idcache_list_next(list, &id_cache))
877 silc_idcache_list_free(list);
881 /* Updates channels that are from `from' to be originated from `to'. */
883 void silc_server_update_channels_by_server(SilcServer server,
884 SilcServerEntry from,
887 SilcIDCacheList list = NULL;
888 SilcIDCacheEntry id_cache = NULL;
889 SilcChannelEntry channel = NULL;
891 SILC_LOG_DEBUG(("Updating channels by server"));
893 if (silc_idcache_get_all(server->global_list->channels, &list)) {
894 if (silc_idcache_list_first(list, &id_cache)) {
896 channel = (SilcChannelEntry)id_cache->context;
897 if (channel->router == from)
898 channel->router = to;
899 if (!silc_idcache_list_next(list, &id_cache))
903 silc_idcache_list_free(list);
907 /* Checks whether given channel has global users. If it does this returns
908 TRUE and FALSE if there is only locally connected clients on the channel. */
910 bool silc_server_channel_has_global(SilcChannelEntry channel)
912 SilcChannelClientEntry chl;
913 SilcHashTableList htl;
915 silc_hash_table_list(channel->user_list, &htl);
916 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
917 if (chl->client->router) {
918 silc_hash_table_list_reset(&htl);
922 silc_hash_table_list_reset(&htl);
927 /* Checks whether given channel has locally connected users. If it does this
928 returns TRUE and FALSE if there is not one locally connected client. */
930 bool silc_server_channel_has_local(SilcChannelEntry channel)
932 SilcChannelClientEntry chl;
933 SilcHashTableList htl;
935 silc_hash_table_list(channel->user_list, &htl);
936 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
937 if (!chl->client->router) {
938 silc_hash_table_list_reset(&htl);
942 silc_hash_table_list_reset(&htl);
947 /* This function removes the channel and all users on the channel, unless
948 the channel is permanent. In this case the channel is disabled but all
949 users are removed from the channel. Returns TRUE if the channel is
950 destroyed totally, and FALSE if it is permanent and remains. */
952 bool silc_server_channel_delete(SilcServer server,
953 SilcChannelEntry channel)
955 SilcChannelClientEntry chl;
956 SilcHashTableList htl;
957 bool delchan = !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH);
960 SILC_LOG_DEBUG(("Deleting %s channel", channel->channel_name));
962 /* Update statistics */
963 if (server->server_type == SILC_ROUTER)
964 server->stat.chanclients -= channel->user_count;
966 /* Totally delete the channel and all users on the channel. The
967 users are deleted automatically in silc_idlist_del_channel. */
968 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
969 if (silc_idlist_del_channel(server->local_list, channel)) {
970 server->stat.my_channels--;
971 if (server->server_type == SILC_ROUTER) {
972 server->stat.channels--;
973 server->stat.cell_channels--;
976 if (silc_idlist_del_channel(server->global_list, channel))
977 if (server->server_type == SILC_ROUTER)
978 server->stat.channels--;
984 /* Channel is permanent, do not remove it, remove only users */
985 channel->disabled = TRUE;
986 silc_hash_table_list(channel->user_list, &htl);
987 while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
988 silc_hash_table_del(chl->client->channels, channel);
989 silc_hash_table_del(channel->user_list, chl->client);
990 channel->user_count--;
992 /* Update statistics */
993 if (SILC_IS_LOCAL(chl->client))
994 server->stat.my_chanclients--;
995 if (server->server_type == SILC_ROUTER) {
996 server->stat.cell_chanclients--;
997 server->stat.chanclients--;
1002 silc_hash_table_list_reset(&htl);
1004 SILC_LOG_DEBUG(("Channel %s remains", channel->channel_name));
1009 /* Returns TRUE if the given client is on the channel. FALSE if not.
1010 This works because we assure that the user list on the channel is
1011 always in up to date thus we can only check the channel list from
1012 `client' which is faster than checking the user list from `channel'. */
1014 bool silc_server_client_on_channel(SilcClientEntry client,
1015 SilcChannelEntry channel,
1016 SilcChannelClientEntry *chl)
1018 if (!client || !channel)
1021 return silc_hash_table_find(client->channels, channel, NULL,
1025 /* Checks string for bad characters and returns TRUE if they are found. */
1027 bool silc_server_name_bad_chars(const char *name, SilcUInt32 name_len)
1031 for (i = 0; i < name_len; i++) {
1032 if (!isascii(name[i]))
1034 if (name[i] <= 32) return TRUE;
1035 if (name[i] == ' ') return TRUE;
1036 if (name[i] == '*') return TRUE;
1037 if (name[i] == '?') return TRUE;
1038 if (name[i] == ',') return TRUE;
1044 /* Modifies the `name' if it includes bad characters and returns new
1045 allocated name that does not include bad characters. */
1047 char *silc_server_name_modify_bad(const char *name, SilcUInt32 name_len)
1050 char *newname = strdup(name);
1052 for (i = 0; i < name_len; i++) {
1053 if (!isascii(newname[i])) newname[i] = '_';
1054 if (newname[i] <= 32) newname[i] = '_';
1055 if (newname[i] == ' ') newname[i] = '_';
1056 if (newname[i] == '*') newname[i] = '_';
1057 if (newname[i] == '?') newname[i] = '_';
1058 if (newname[i] == ',') newname[i] = '_';
1064 /* Find number of sockets by IP address indicated by `ip'. Returns 0 if
1065 socket connections with the IP address does not exist. */
1067 SilcUInt32 silc_server_num_sockets_by_ip(SilcServer server, const char *ip,
1068 SilcSocketType type)
1072 for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
1073 if (server->sockets[i] && !strcmp(server->sockets[i]->ip, ip) &&
1074 server->sockets[i]->type == type)
1081 /* Find number of sockets by IP address indicated by remote host, indicatd
1082 by `ip' or `hostname', `port', and `type'. Returns 0 if socket connections
1083 does not exist. If `ip' is provided then `hostname' is ignored. */
1085 SilcUInt32 silc_server_num_sockets_by_remote(SilcServer server,
1087 const char *hostname,
1089 SilcSocketType type)
1093 if (!ip && !hostname)
1096 for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
1097 if (server->sockets[i] &&
1098 ((ip && !strcmp(server->sockets[i]->ip, ip)) ||
1099 (hostname && !strcmp(server->sockets[i]->hostname, hostname))) &&
1100 server->sockets[i]->port == port &&
1101 server->sockets[i]->type == type)
1108 /* Finds locally cached public key by the public key received in the SKE.
1109 If we have it locally cached then we trust it and will use it in the
1110 authentication protocol. Returns the locally cached public key or NULL
1111 if we do not find the public key. */
1113 SilcPublicKey silc_server_find_public_key(SilcServer server,
1114 SilcHashTable local_public_keys,
1115 SilcPublicKey remote_public_key)
1117 SilcPublicKey cached_key;
1119 SILC_LOG_DEBUG(("Find remote public key (%d keys in local cache)",
1120 silc_hash_table_count(local_public_keys)));
1122 if (!silc_hash_table_find_ext(local_public_keys, remote_public_key,
1123 (void **)&cached_key, NULL,
1124 silc_hash_public_key, NULL,
1125 silc_hash_public_key_compare, NULL)) {
1126 SILC_LOG_ERROR(("Public key not found"));
1130 SILC_LOG_DEBUG(("Found public key"));
1135 /* This returns the first public key from the table of public keys. This
1136 is used only in cases where single public key exists in the table and
1137 we want to get a pointer to it. For public key tables that has multiple
1138 keys in it the silc_server_find_public_key must be used. */
1140 SilcPublicKey silc_server_get_public_key(SilcServer server,
1141 SilcHashTable local_public_keys)
1143 SilcPublicKey cached_key;
1144 SilcHashTableList htl;
1146 SILC_LOG_DEBUG(("Start"));
1148 assert(silc_hash_table_count(local_public_keys) < 2);
1150 silc_hash_table_list(local_public_keys, &htl);
1151 if (!silc_hash_table_get(&htl, NULL, (void **)&cached_key))
1153 silc_hash_table_list_reset(&htl);
1158 /* Check whether the connection `sock' is allowed to connect to us. This
1159 checks for example whether there is too much connections for this host,
1160 and required version for the host etc. */
1162 bool silc_server_connection_allowed(SilcServer server,
1163 SilcSocketConnection sock,
1164 SilcSocketType type,
1165 SilcServerConfigConnParams *global,
1166 SilcServerConfigConnParams *params,
1169 SilcUInt32 conn_number = (type == SILC_SOCKET_TYPE_CLIENT ?
1170 server->stat.my_clients :
1171 type == SILC_SOCKET_TYPE_SERVER ?
1172 server->stat.my_servers :
1173 server->stat.my_routers);
1174 SilcUInt32 num_sockets, max_hosts, max_per_host;
1175 SilcUInt32 r_protocol_version, l_protocol_version;
1176 SilcUInt32 r_software_version, l_software_version;
1177 char *r_vendor_version = NULL, *l_vendor_version;
1179 SILC_LOG_DEBUG(("Checking whether connection is allowed"));
1183 l_protocol_version =
1184 silc_version_to_num(params && params->version_protocol ?
1185 params->version_protocol :
1186 global->version_protocol);
1187 l_software_version =
1188 silc_version_to_num(params && params->version_software ?
1189 params->version_software :
1190 global->version_software);
1191 l_vendor_version = (params && params->version_software_vendor ?
1192 params->version_software_vendor :
1193 global->version_software_vendor);
1195 if (ske && silc_ske_parse_version(ske, &r_protocol_version, NULL,
1196 &r_software_version, NULL,
1197 &r_vendor_version)) {
1198 sock->version = r_protocol_version;
1200 /* Match protocol version */
1201 if (l_protocol_version && r_protocol_version &&
1202 r_protocol_version < l_protocol_version) {
1203 SILC_LOG_INFO(("Connection %s (%s) is too old version",
1204 sock->hostname, sock->ip));
1205 silc_server_disconnect_remote(server, sock,
1206 SILC_STATUS_ERR_BAD_VERSION,
1207 "You support too old protocol version");
1211 /* Math software version */
1212 if (l_software_version && r_software_version &&
1213 r_software_version < l_software_version) {
1214 SILC_LOG_INFO(("Connection %s (%s) is too old version",
1215 sock->hostname, sock->ip));
1216 silc_server_disconnect_remote(server, sock,
1217 SILC_STATUS_ERR_BAD_VERSION,
1218 "You support too old software version");
1222 /* Regex match vendor version */
1223 if (l_vendor_version && r_vendor_version &&
1224 !silc_string_match(l_vendor_version, r_vendor_version)) {
1225 SILC_LOG_INFO(("Connection %s (%s) is unsupported version",
1226 sock->hostname, sock->ip));
1227 silc_server_disconnect_remote(server, sock,
1228 SILC_STATUS_ERR_BAD_VERSION,
1229 "Your software is not supported");
1233 silc_free(r_vendor_version);
1235 /* Check for maximum connections limit */
1237 num_sockets = silc_server_num_sockets_by_ip(server, sock->ip, type);
1238 max_hosts = (params ? params->connections_max : global->connections_max);
1239 max_per_host = (params ? params->connections_max_per_host :
1240 global->connections_max_per_host);
1242 if (max_hosts && conn_number >= max_hosts) {
1243 SILC_LOG_INFO(("Server is full, closing %s (%s) connection",
1244 sock->hostname, sock->ip));
1245 silc_server_disconnect_remote(server, sock,
1246 SILC_STATUS_ERR_RESOURCE_LIMIT,
1247 "Server is full, try again later");
1251 if (num_sockets >= max_per_host) {
1252 SILC_LOG_INFO(("Too many connections from %s (%s), closing connection",
1253 sock->hostname, sock->ip));
1254 silc_server_disconnect_remote(server, sock,
1255 SILC_STATUS_ERR_RESOURCE_LIMIT,
1256 "Too many connections from your host");
1263 /* Checks that client has rights to add or remove channel modes. If any
1264 of the checks fails FALSE is returned. */
1266 bool silc_server_check_cmode_rights(SilcServer server,
1267 SilcChannelEntry channel,
1268 SilcChannelClientEntry client,
1271 bool is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1272 bool is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1274 /* Check whether has rights to change anything */
1275 if (!is_op && !is_fo)
1278 /* Check whether has rights to change everything */
1282 /* Founder implies operator */
1286 /* We know that client is channel operator, check that they are not
1287 changing anything that requires channel founder rights. Rest of the
1288 modes are available automatically for channel operator. */
1290 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1291 if (is_op && !is_fo)
1294 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1295 if (is_op && !is_fo)
1300 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1301 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
1302 if (is_op && !is_fo)
1306 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1307 if (is_op && !is_fo)
1312 if (mode & SILC_CHANNEL_MODE_CIPHER) {
1313 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
1314 if (is_op && !is_fo)
1318 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1319 if (is_op && !is_fo)
1324 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1325 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
1326 if (is_op && !is_fo)
1330 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1331 if (is_op && !is_fo)
1336 if (mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1337 if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS)) {
1338 if (is_op && !is_fo)
1342 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1343 if (is_op && !is_fo)
1348 if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1349 if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS)) {
1350 if (is_op && !is_fo)
1354 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1355 if (is_op && !is_fo)
1363 /* Check that the client has rights to change its user mode. Returns
1364 FALSE if setting some mode is not allowed. */
1366 bool silc_server_check_umode_rights(SilcServer server,
1367 SilcClientEntry client,
1370 bool server_op = FALSE, router_op = FALSE;
1372 if (mode & SILC_UMODE_SERVER_OPERATOR) {
1373 /* Cannot set server operator mode (must use OPER command) */
1374 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR))
1377 /* Remove the server operator rights */
1378 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
1382 if (mode & SILC_UMODE_ROUTER_OPERATOR) {
1383 /* Cannot set router operator mode (must use SILCOPER command) */
1384 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR))
1387 /* Remove the router operator rights */
1388 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
1393 SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR);
1395 SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR);
1400 /* This function is used to send the notify packets and motd to the
1401 incoming client connection. */
1403 void silc_server_send_connect_notifys(SilcServer server,
1404 SilcSocketConnection sock,
1405 SilcClientEntry client)
1407 SilcIDListData idata = (SilcIDListData)client;
1409 SILC_LOG_DEBUG(("Send welcome notifys"));
1411 /* Send some nice info to the client */
1412 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1413 ("Welcome to the SILC Network %s",
1415 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1416 ("Your host is %s, running version %s",
1417 server->server_name, server_version));
1419 if (server->server_type == SILC_ROUTER) {
1420 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1421 ("There are %d clients, %d servers and %d "
1422 "routers in SILC Network",
1423 server->stat.clients, server->stat.servers + 1,
1424 server->stat.routers));
1426 if (server->stat.clients && server->stat.servers + 1)
1427 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1428 ("There are %d clients, %d servers and %d "
1429 "routers in SILC Network",
1430 server->stat.clients, server->stat.servers + 1,
1431 (server->standalone ? 0 :
1432 !server->stat.routers ? 1 :
1433 server->stat.routers)));
1436 if (server->stat.cell_clients && server->stat.cell_servers + 1)
1437 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1438 ("There are %d clients on %d server in our cell",
1439 server->stat.cell_clients,
1440 server->stat.cell_servers + 1));
1441 if (server->server_type == SILC_ROUTER) {
1442 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1443 ("I have %d clients, %d channels, %d servers and "
1445 server->stat.my_clients,
1446 server->stat.my_channels,
1447 server->stat.my_servers,
1448 server->stat.my_routers));
1450 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1451 ("I have %d clients and %d channels formed",
1452 server->stat.my_clients,
1453 server->stat.my_channels));
1456 if (server->stat.server_ops || server->stat.router_ops)
1457 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1458 ("There are %d server operators and %d router "
1460 server->stat.server_ops,
1461 server->stat.router_ops));
1462 if (server->stat.my_router_ops + server->stat.my_server_ops)
1463 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1464 ("I have %d operators online",
1465 server->stat.my_router_ops +
1466 server->stat.my_server_ops));
1468 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1469 ("Your connection is secured with %s cipher, "
1470 "key length %d bits",
1471 idata->send_key->cipher->name,
1472 idata->send_key->cipher->key_len));
1473 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1474 ("Your current nickname is %s",
1478 silc_server_send_motd(server, sock);
1481 /* Kill the client indicated by `remote_client' sending KILLED notify
1482 to the client, to all channels client has joined and to primary
1483 router if needed. The killed client is also removed from all channels. */
1485 void silc_server_kill_client(SilcServer server,
1486 SilcClientEntry remote_client,
1487 const char *comment,
1489 SilcIdType killer_id_type)
1491 SilcBuffer killed, killer;
1493 SILC_LOG_DEBUG(("Killing client %s",
1494 silc_id_render(remote_client->id, SILC_ID_CLIENT)));
1496 /* Send the KILL notify packets. First send it to the channel, then
1497 to our primary router and then directly to the client who is being
1498 killed right now. */
1500 killed = silc_id_payload_encode(remote_client->id, SILC_ID_CLIENT);
1501 killer = silc_id_payload_encode(killer_id, killer_id_type);
1503 /* Send KILLED notify to the channels. It is not sent to the client
1504 as it will be sent differently destined directly to the client and not
1506 silc_server_send_notify_on_channels(server, remote_client,
1507 remote_client, SILC_NOTIFY_TYPE_KILLED,
1508 3, killed->data, killed->len,
1509 comment, comment ? strlen(comment) : 0,
1510 killer->data, killer->len);
1512 /* Send KILLED notify to primary route */
1513 silc_server_send_notify_killed(server, SILC_PRIMARY_ROUTE(server),
1514 SILC_BROADCAST(server), remote_client->id,
1515 comment, killer_id, killer_id_type);
1517 /* Send KILLED notify to the client directly */
1518 if (remote_client->connection || remote_client->router)
1519 silc_server_send_notify_killed(server, remote_client->connection ?
1520 remote_client->connection :
1521 remote_client->router->connection, FALSE,
1522 remote_client->id, comment,
1523 killer_id, killer_id_type);
1525 /* Remove the client from all channels. This generates new keys to the
1526 channels as well. */
1527 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
1530 /* Remove the client entry, If it is locally connected then we will also
1531 disconnect the client here */
1532 if (remote_client->connection) {
1533 /* Remove locally conneted client */
1534 SilcSocketConnection sock = remote_client->connection;
1535 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
1536 silc_server_close_connection(server, sock);
1538 /* Update statistics */
1539 server->stat.clients--;
1540 if (server->stat.cell_clients)
1541 server->stat.cell_clients--;
1542 SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
1543 SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
1545 if (SILC_IS_LOCAL(remote_client)) {
1546 server->stat.my_clients--;
1547 silc_schedule_task_del_by_context(server->schedule, remote_client);
1548 silc_idlist_del_data(remote_client);
1551 /* Remove remote client */
1552 if (!silc_idlist_del_client(server->global_list, remote_client)) {
1553 /* Remove this client from watcher list if it is */
1554 silc_server_del_from_watcher_list(server, remote_client);
1555 silc_idlist_del_client(server->local_list, remote_client);
1559 silc_buffer_free(killer);
1560 silc_buffer_free(killed);
1565 SilcClientEntry client;
1566 SilcNotifyType notify;
1567 const char *new_nick;
1568 } WatcherNotifyContext;
1571 silc_server_check_watcher_list_foreach(void *key, void *context,
1574 WatcherNotifyContext *notify = user_context;
1575 SilcClientEntry entry = context;
1576 SilcSocketConnection sock;
1578 if (entry == notify->client)
1581 sock = silc_server_get_client_route(notify->server, NULL, 0, entry->id,
1584 SILC_LOG_DEBUG(("Sending WATCH notify to %s",
1585 silc_id_render(entry->id, SILC_ID_CLIENT)));
1587 /* Send the WATCH notify */
1588 silc_server_send_notify_watch(notify->server, sock, entry,
1590 notify->new_nick ? notify->new_nick :
1591 (const char *)notify->client->nickname,
1596 /* This function checks whether the `client' nickname is being watched
1597 by someone, and notifies the watcher of the notify change of notify
1598 type indicated by `notify'. */
1600 bool silc_server_check_watcher_list(SilcServer server,
1601 SilcClientEntry client,
1602 const char *new_nick,
1603 SilcNotifyType notify)
1605 unsigned char hash[16];
1606 WatcherNotifyContext n;
1608 SILC_LOG_DEBUG(("Checking watcher list %s",
1609 client->nickname ? client->nickname : (unsigned char *)""));
1611 /* If the watching is rejected by the client do nothing */
1612 if (client->mode & SILC_UMODE_REJECT_WATCHING)
1615 /* Make hash from the nick, or take it from Client ID */
1616 if (client->nickname) {
1618 memset(nick, 0, sizeof(nick));
1619 silc_to_lower(client->nickname, nick, sizeof(nick) - 1);
1620 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
1622 memset(hash, 0, sizeof(hash));
1623 memcpy(hash, client->id->hash, sizeof(client->id->hash));
1628 n.new_nick = new_nick;
1631 /* Send notify to all watchers */
1632 silc_hash_table_find_foreach(server->watcher_list, hash,
1633 silc_server_check_watcher_list_foreach, &n);
1638 /* Remove the `client' from watcher list. After calling this the `client'
1639 is not watching any nicknames. */
1641 bool silc_server_del_from_watcher_list(SilcServer server,
1642 SilcClientEntry client)
1644 SilcHashTableList htl;
1646 SilcClientEntry entry;
1649 silc_hash_table_list(server->watcher_list, &htl);
1650 while (silc_hash_table_get(&htl, &key, (void **)&entry)) {
1651 if (entry == client) {
1652 silc_hash_table_del_by_context(server->watcher_list, key, client);
1655 SILC_LOG_DEBUG(("Removing %s from WATCH list",
1656 silc_id_render(client->id, SILC_ID_CLIENT)));
1658 /* Now check whether there still exists entries with this key, if not
1659 then free the key to not leak memory. */
1660 if (!silc_hash_table_find(server->watcher_list, key, NULL, NULL))
1666 silc_hash_table_list_reset(&htl);
1671 /* Force the client indicated by `chl' to change the channel user mode
1672 on channel indicated by `channel' to `forced_mode'. */
1674 bool silc_server_force_cumode_change(SilcServer server,
1675 SilcSocketConnection sock,
1676 SilcChannelEntry channel,
1677 SilcChannelClientEntry chl,
1678 SilcUInt32 forced_mode)
1680 SilcBuffer idp1, idp2;
1681 unsigned char cumode[4];
1683 SILC_LOG_DEBUG(("Enforcing sender to change mode"));
1686 silc_server_send_notify_cumode(server, sock, FALSE, channel, forced_mode,
1687 server->id, SILC_ID_SERVER,
1688 chl->client->id, NULL);
1690 idp1 = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1691 idp2 = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
1692 SILC_PUT32_MSB(forced_mode, cumode);
1693 silc_server_send_notify_to_channel(server, sock, channel, FALSE,
1694 SILC_NOTIFY_TYPE_CUMODE_CHANGE,
1695 3, idp1->data, idp1->len,
1696 cumode, sizeof(cumode),
1697 idp2->data, idp2->len);
1698 silc_buffer_free(idp1);
1699 silc_buffer_free(idp2);
1704 /* Find active socket connection by the IP address and port indicated by
1705 `ip' and `port', and socket connection type of `type'. */
1707 SilcSocketConnection
1708 silc_server_find_socket_by_host(SilcServer server,
1709 SilcSocketType type,
1710 const char *ip, SilcUInt16 port)
1714 for (i = 0; i < server->config->param.connections_max; i++) {
1715 if (!server->sockets[i])
1717 if (!strcmp(server->sockets[i]->ip, ip) &&
1718 (!port || server->sockets[i]->port == port) &&
1719 server->sockets[i]->type == type)
1720 return server->sockets[i];