5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2002 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
21 #include "serverincludes.h"
22 #include "server_internal.h"
24 extern char *server_version;
26 /* Removes the client from channels and possibly removes the channels
27 as well. After removing those channels that exist, their channel
28 keys are regnerated. This is called only by the function
29 silc_server_remove_clients_by_server. */
32 silc_server_remove_clients_channels(SilcServer server,
33 SilcServerEntry server_entry,
34 SilcHashTable clients,
35 SilcClientEntry client,
36 SilcHashTable channels)
38 SilcChannelEntry channel;
39 SilcChannelClientEntry chl, chl2;
40 SilcHashTableList htl, htl2;
45 SILC_LOG_DEBUG(("Remove client from all channels"));
47 if (silc_hash_table_find(clients, client, NULL, NULL))
48 silc_hash_table_del(clients, client);
50 /* Remove the client from all channels. The client is removed from
51 the channels' user list. */
52 silc_hash_table_list(client->channels, &htl);
53 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
54 channel = chl->channel;
56 /* Remove channel if this is last client leaving the channel, unless
57 the channel is permanent. */
58 if (server->server_type != SILC_SERVER &&
59 silc_hash_table_count(channel->user_list) < 2) {
60 if (silc_hash_table_find(channels, channel, NULL, NULL))
61 silc_hash_table_del(channels, channel);
62 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
63 silc_server_channel_delete(server, channel);
67 silc_hash_table_del(client->channels, channel);
68 silc_hash_table_del(channel->user_list, chl->client);
69 channel->user_count--;
71 /* If there is no global users on the channel anymore mark the channel
72 as local channel. Do not check if the removed client is local client. */
73 if (server->server_type != SILC_ROUTER && channel->global_users &&
74 chl->client->router && !silc_server_channel_has_global(channel))
75 channel->global_users = FALSE;
79 /* Update statistics */
80 if (SILC_IS_LOCAL(client))
81 server->stat.my_chanclients--;
82 if (server->server_type == SILC_ROUTER) {
83 server->stat.cell_chanclients--;
84 server->stat.chanclients--;
87 /* If there is not at least one local user on the channel then we don't
88 need the channel entry anymore, we can remove it safely, unless the
89 channel is permanent channel */
90 if (server->server_type == SILC_SERVER &&
91 !silc_server_channel_has_local(channel)) {
92 if (silc_hash_table_find(channels, channel, NULL, NULL))
93 silc_hash_table_del(channels, channel);
94 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
95 silc_server_channel_delete(server, channel);
99 /* Mark other local clients to the table of clients whom will receive
100 the SERVER_SIGNOFF notify. */
101 silc_hash_table_list(channel->user_list, &htl2);
102 while (silc_hash_table_get(&htl2, NULL, (void **)&chl2)) {
103 SilcClientEntry c = chl2->client;
107 /* Add client to table, if it's not from the signoff server */
108 if (c->router != server_entry &&
109 !silc_hash_table_find(clients, c, NULL, NULL))
110 silc_hash_table_add(clients, c, c);
112 silc_hash_table_list_reset(&htl2);
114 /* Add the channel to the the channels list to regenerate the
116 if (!silc_hash_table_find(channels, channel, NULL, NULL))
117 silc_hash_table_add(channels, channel, channel);
119 silc_hash_table_list_reset(&htl);
122 /* This function removes all client entries that are originated from
123 `router' and are owned by `entry'. `router' and `entry' can be same
124 too. If `server_signoff' is TRUE then SERVER_SIGNOFF notify is
125 distributed to our local clients. */
127 bool silc_server_remove_clients_by_server(SilcServer server,
128 SilcServerEntry router,
129 SilcServerEntry entry,
132 SilcIDCacheList list = NULL;
133 SilcIDCacheEntry id_cache = NULL;
134 SilcClientEntry client = NULL;
136 unsigned char **argv = NULL;
137 SilcUInt32 *argv_lens = NULL, *argv_types = NULL, argc = 0;
138 SilcHashTableList htl;
139 SilcChannelEntry channel;
140 SilcHashTable channels, clients;
143 if (!(entry->data.status & SILC_IDLIST_STATUS_REGISTERED))
146 SILC_LOG_DEBUG(("Removing clients by %s",
147 entry->server_name ? entry->server_name : "server"));
152 /* Allocate the hash table that holds the channels that require
153 channel key re-generation after we've removed this server's clients
154 from the channels. */
155 channels = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL,
157 clients = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL,
160 if (server_signoff) {
161 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
162 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
163 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) * (argc + 1));
164 argv_types = silc_realloc(argv_types, sizeof(*argv_types) * (argc + 1));
165 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
166 memcpy(argv[argc], idp->data, idp->len);
167 argv_lens[argc] = idp->len;
168 argv_types[argc] = argc + 1;
170 silc_buffer_free(idp);
173 if (silc_idcache_get_all(server->local_list->clients, &list)) {
174 if (silc_idcache_list_first(list, &id_cache)) {
176 client = (SilcClientEntry)id_cache->context;
178 /* If client is not registered, is not originated from `router'
179 and is not owned by `entry', skip it. */
180 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
181 client->router != router ||
182 (router != entry && !SILC_ID_COMPARE(client->id, entry->id,
183 client->id->ip.data_len))) {
184 if (!silc_idcache_list_next(list, &id_cache))
190 if (server_signoff) {
191 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
192 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
193 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
195 argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
197 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
198 memcpy(argv[argc], idp->data, idp->len);
199 argv_lens[argc] = idp->len;
200 argv_types[argc] = argc + 1;
202 silc_buffer_free(idp);
205 /* Update statistics */
206 server->stat.clients--;
207 if (server->stat.cell_clients)
208 server->stat.cell_clients--;
209 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
210 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
212 silc_server_remove_clients_channels(server, entry, clients,
214 silc_server_del_from_watcher_list(server, client);
216 /* Remove the client entry */
217 if (!server_signoff) {
218 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
219 id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
221 silc_idlist_del_data(client);
222 silc_idlist_del_client(server->local_list, client);
225 if (!silc_idcache_list_next(list, &id_cache))
229 silc_idcache_list_free(list);
232 if (silc_idcache_get_all(server->global_list->clients, &list)) {
234 if (silc_idcache_list_first(list, &id_cache)) {
236 client = (SilcClientEntry)id_cache->context;
238 /* If client is not registered, is not originated from `router'
239 and is not owned by `entry', skip it. */
240 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
241 client->router != router ||
242 (router != entry && !SILC_ID_COMPARE(client->id, entry->id,
243 client->id->ip.data_len))) {
244 if (!silc_idcache_list_next(list, &id_cache))
250 if (server_signoff) {
251 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
252 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
253 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
255 argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
257 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
258 memcpy(argv[argc], idp->data, idp->len);
259 argv_lens[argc] = idp->len;
260 argv_types[argc] = argc + 1;
262 silc_buffer_free(idp);
265 /* Update statistics */
266 server->stat.clients--;
267 if (server->stat.cell_clients)
268 server->stat.cell_clients--;
269 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
270 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
272 silc_server_remove_clients_channels(server, entry, clients,
274 silc_server_del_from_watcher_list(server, client);
276 /* Remove the client entry */
277 if (!server_signoff) {
278 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
279 id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
281 silc_idlist_del_data(client);
282 silc_idlist_del_client(server->global_list, client);
285 if (!silc_idcache_list_next(list, &id_cache))
289 silc_idcache_list_free(list);
292 /* Return now if we are shutting down */
293 if (server->server_shutdown) {
294 silc_hash_table_free(channels);
296 if (server_signoff) {
297 for (i = 0; i < argc; i++)
300 silc_free(argv_lens);
301 silc_free(argv_types);
302 silc_hash_table_free(clients);
307 /* Send the SERVER_SIGNOFF notify */
308 if (server_signoff) {
309 SilcBuffer args, not;
311 SILC_LOG_DEBUG(("Sending SERVER_SIGNOFF for %s with %d clients",
312 silc_id_render(entry->id, SILC_ID_SERVER), argc - 1));
314 /* Send SERVER_SIGNOFF notify to our primary router */
315 if (server->router != entry) {
316 args = silc_argument_payload_encode(1, argv, argv_lens,
318 silc_server_send_notify_args(server, SILC_PRIMARY_ROUTE(server),
319 SILC_BROADCAST(server),
320 SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
322 silc_buffer_free(args);
325 /* Send to local clients. We also send the list of client ID's that
326 is to be removed for those servers that would like to use that list. */
327 args = silc_argument_payload_encode(argc, argv, argv_lens,
329 not = silc_notify_payload_encode_args(SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
331 silc_server_packet_send_clients(server, clients,
332 SILC_PACKET_NOTIFY, 0, FALSE,
333 not->data, not->len, FALSE);
335 /* Send notify also to local backup routers */
336 silc_server_backup_send(server, NULL, SILC_PACKET_NOTIFY, 0,
337 not->data, not->len, FALSE, TRUE);
339 silc_buffer_free(args);
340 silc_buffer_free(not);
341 for (i = 0; i < argc; i++)
344 silc_free(argv_lens);
345 silc_free(argv_types);
346 silc_hash_table_free(clients);
349 /* We must now re-generate the channel key for all channels that had
350 this server's client(s) on the channel. As they left the channel we
351 must re-generate the channel key. */
352 silc_hash_table_list(channels, &htl);
353 while (silc_hash_table_get(&htl, NULL, (void **)&channel)) {
354 if (!silc_server_create_channel_key(server, channel, 0)) {
355 silc_hash_table_list_reset(&htl);
356 silc_hash_table_free(channels);
360 /* Do not send the channel key if private channel key mode is set */
361 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY || !channel->channel_key)
364 silc_server_send_channel_key(server, NULL, channel,
365 server->server_type == SILC_ROUTER ?
366 FALSE : !server->standalone);
368 silc_hash_table_list_reset(&htl);
369 silc_hash_table_free(channels);
374 static SilcServerEntry
375 silc_server_update_clients_by_real_server(SilcServer server,
376 SilcServerEntry from,
378 SilcClientEntry client,
380 SilcIDCacheEntry client_cache)
382 SilcServerEntry server_entry;
383 SilcIDCacheEntry id_cache = NULL;
384 SilcIDCacheList list;
385 bool tolocal = (to == server->id_entry);
387 if (!silc_idcache_get_all(server->local_list->servers, &list))
390 if (silc_idcache_list_first(list, &id_cache)) {
392 server_entry = (SilcServerEntry)id_cache->context;
393 if (server_entry != from &&
394 (tolocal || server_entry != server->id_entry) &&
395 SILC_ID_COMPARE(server_entry->id, client->id,
396 client->id->ip.data_len)) {
397 SILC_LOG_DEBUG(("Found (local) %s",
398 silc_id_render(server_entry->id, SILC_ID_SERVER)));
400 if (!server_entry->data.send_key && server_entry->router) {
401 SILC_LOG_DEBUG(("Server not locally connected, use its router"));
402 /* If the client is not marked as local then move it to local list
403 since the server is local. */
405 SILC_LOG_DEBUG(("Moving client to local list"));
406 silc_idcache_add(server->local_list->clients, client_cache->name,
407 client_cache->id, client_cache->context,
408 client_cache->expire, NULL);
409 silc_idcache_del_by_context(server->global_list->clients, client);
411 server_entry = server_entry->router;
413 /* If the client is not marked as local then move it to local list
414 since the server is local. */
415 if (server_entry->server_type != SILC_BACKUP_ROUTER && !local) {
416 SILC_LOG_DEBUG(("Moving client to local list"));
417 silc_idcache_add(server->local_list->clients, client_cache->name,
418 client_cache->id, client_cache->context,
419 client_cache->expire, NULL);
420 silc_idcache_del_by_context(server->global_list->clients, client);
424 silc_idcache_list_free(list);
428 if (!silc_idcache_list_next(list, &id_cache))
433 silc_idcache_list_free(list);
435 if (!silc_idcache_get_all(server->global_list->servers, &list))
438 if (silc_idcache_list_first(list, &id_cache)) {
440 server_entry = (SilcServerEntry)id_cache->context;
441 if (server_entry != from && server_entry != server->id_entry &&
442 (tolocal || server_entry != server->id_entry) &&
443 SILC_ID_COMPARE(server_entry->id, client->id,
444 client->id->ip.data_len)) {
445 SILC_LOG_DEBUG(("Found (global) %s",
446 silc_id_render(server_entry->id, SILC_ID_SERVER)));
448 if (!server_entry->data.send_key && server_entry->router) {
449 SILC_LOG_DEBUG(("Server not locally connected, use its router"));
450 /* If the client is marked as local then move it to global list
451 since the server is global. */
453 SILC_LOG_DEBUG(("Moving client to global list"));
454 silc_idcache_add(server->global_list->clients, client_cache->name,
455 client_cache->id, client_cache->context, 0, NULL);
456 silc_idcache_del_by_context(server->local_list->clients, client);
458 server_entry = server_entry->router;
460 /* If the client is marked as local then move it to global list
461 since the server is global. */
462 if (server_entry->server_type != SILC_BACKUP_ROUTER && local) {
463 SILC_LOG_DEBUG(("Moving client to global list"));
464 silc_idcache_add(server->global_list->clients, client_cache->name,
465 client_cache->id, client_cache->context, 0, NULL);
466 silc_idcache_del_by_context(server->local_list->clients, client);
470 silc_idcache_list_free(list);
474 if (!silc_idcache_list_next(list, &id_cache))
479 silc_idcache_list_free(list);
484 /* Updates the clients that are originated from the `from' to be originated
485 from the `to'. If the `resolve_real_server' is TRUE then this will
486 attempt to figure out which clients really are originated from the
487 `from' and which are originated from a server that we have connection
488 to, when we've acting as backup router. If it is FALSE the `to' will
489 be the new source. */
491 void silc_server_update_clients_by_server(SilcServer server,
492 SilcServerEntry from,
494 bool resolve_real_server)
496 SilcIDCacheList list = NULL;
497 SilcIDCacheEntry id_cache = NULL;
498 SilcClientEntry client = NULL;
502 if (silc_idcache_get_all(server->global_list->clients, &list)) {
503 if (silc_idcache_list_first(list, &id_cache)) {
505 client = (SilcClientEntry)id_cache->context;
507 /* If entry is disabled skip it. If entry is local to us, do not
508 switch it to anyone else, it is ours so skip it. */
509 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
510 SILC_IS_LOCAL(client)) {
511 if (!silc_idcache_list_next(list, &id_cache))
517 SILC_LOG_DEBUG(("Client %s",
518 silc_id_render(client->id, SILC_ID_CLIENT)));
520 SILC_LOG_DEBUG(("Client->router %s",
521 silc_id_render(client->router->id, SILC_ID_SERVER)));
524 if (client->router == from) {
525 if (resolve_real_server) {
527 silc_server_update_clients_by_real_server(server, from, to,
530 if (!client->router) {
531 if (server->server_type == SILC_ROUTER)
532 client->router = from;
541 /* All are changed */
546 SILC_LOG_DEBUG(("Client changed to %s",
547 silc_id_render(client->router->id, SILC_ID_SERVER)));
549 if (!silc_idcache_list_next(list, &id_cache))
553 silc_idcache_list_free(list);
557 if (silc_idcache_get_all(server->local_list->clients, &list)) {
558 if (silc_idcache_list_first(list, &id_cache)) {
560 client = (SilcClientEntry)id_cache->context;
562 /* If entry is disabled skip it. If entry is local to us, do not
563 switch it to anyone else, it is ours so skip it. */
564 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
565 SILC_IS_LOCAL(client)) {
566 if (!silc_idcache_list_next(list, &id_cache))
572 SILC_LOG_DEBUG(("Client %s",
573 silc_id_render(client->id, SILC_ID_CLIENT)));
575 SILC_LOG_DEBUG(("Client->router %s",
576 silc_id_render(client->router->id, SILC_ID_SERVER)));
579 if (client->router == from) {
580 if (resolve_real_server) {
582 silc_server_update_clients_by_real_server(server, from, to,
586 client->router = from;
592 /* All are changed */
597 SILC_LOG_DEBUG(("Client changed to %s",
598 silc_id_render(client->router->id, SILC_ID_SERVER)));
600 if (!silc_idcache_list_next(list, &id_cache))
604 silc_idcache_list_free(list);
608 /* Updates servers that are from `from' to be originated from `to'. This
609 will also update the server's connection to `to's connection. */
611 void silc_server_update_servers_by_server(SilcServer server,
612 SilcServerEntry from,
615 SilcIDCacheList list = NULL;
616 SilcIDCacheEntry id_cache = NULL;
617 SilcServerEntry server_entry = NULL;
619 SILC_LOG_DEBUG(("Updating servers"));
621 if (silc_idcache_get_all(server->local_list->servers, &list)) {
622 if (silc_idcache_list_first(list, &id_cache)) {
624 server_entry = (SilcServerEntry)id_cache->context;
626 /* If entry is local to us, do not switch it to any anyone else,
628 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
629 server_entry == from) {
630 if (!silc_idcache_list_next(list, &id_cache))
636 /* If we are standalone router, any server that is not directly
637 connected to cannot exist anymore. If we are not standalone
638 we update it correctly. */
639 if (server->server_type == SILC_ROUTER && server->standalone) {
640 silc_server_backup_del(server, server_entry);
641 silc_server_backup_replaced_del(server, server_entry);
642 silc_idlist_del_data(server_entry);
643 silc_idlist_del_server(server->local_list, server_entry);
644 server->stat.servers--;
645 server->stat.cell_servers--;
647 /* XXX if we are not standalone, do a check from local config
648 whether this server is in our cell, but not connected to
649 us (in which case we must remove it). */
651 if (server_entry->router == from) {
652 SILC_LOG_DEBUG(("Updating server (local) %s",
653 server_entry->server_name ?
654 server_entry->server_name : ""));
655 server_entry->router = to;
656 server_entry->connection = to->connection;
660 if (!silc_idcache_list_next(list, &id_cache))
664 silc_idcache_list_free(list);
667 if (silc_idcache_get_all(server->global_list->servers, &list)) {
668 if (silc_idcache_list_first(list, &id_cache)) {
670 server_entry = (SilcServerEntry)id_cache->context;
672 /* If entry is local to us, do not switch it to anyone else,
674 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
675 server_entry == from) {
676 if (!silc_idcache_list_next(list, &id_cache))
682 /* If we are standalone router, any server that is not directly
683 connected to cannot exist anymore. If we are not standalone
684 we update it correctly. */
685 if (server->server_type == SILC_ROUTER && server->standalone) {
686 silc_server_backup_del(server, server_entry);
687 silc_server_backup_replaced_del(server, server_entry);
688 silc_idlist_del_data(server_entry);
689 silc_idlist_del_server(server->global_list, server_entry);
690 server->stat.servers--;
691 server->stat.cell_servers--;
693 /* XXX if we are not standalone, do a check from local config
694 whether this server is in our cell, but not connected to
695 us (in which case we must remove it). */
697 if (server_entry->router == from) {
698 SILC_LOG_DEBUG(("Updating server (global) %s",
699 server_entry->server_name ?
700 server_entry->server_name : ""));
701 server_entry->router = to;
702 server_entry->connection = to->connection;
706 if (!silc_idcache_list_next(list, &id_cache))
710 silc_idcache_list_free(list);
715 /* Toggles the enabled/disabled status of local server connections. Packets
716 can be sent to the servers when `toggle_enabled' is TRUE and will be
717 dropped if `toggle_enabled' is FALSE, after this function is called. */
719 void silc_server_local_servers_toggle_enabled(SilcServer server,
722 SilcIDCacheList list = NULL;
723 SilcIDCacheEntry id_cache = NULL;
724 SilcServerEntry server_entry = NULL;
726 if (silc_idcache_get_all(server->local_list->servers, &list)) {
727 if (silc_idcache_list_first(list, &id_cache)) {
729 server_entry = (SilcServerEntry)id_cache->context;
730 if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry) {
731 if (!silc_idcache_list_next(list, &id_cache))
738 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
740 server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
742 if (!silc_idcache_list_next(list, &id_cache))
746 silc_idcache_list_free(list);
749 if (silc_idcache_get_all(server->global_list->servers, &list)) {
750 if (silc_idcache_list_first(list, &id_cache)) {
752 server_entry = (SilcServerEntry)id_cache->context;
753 if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry) {
754 if (!silc_idcache_list_next(list, &id_cache))
761 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
763 server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
765 if (!silc_idcache_list_next(list, &id_cache))
769 silc_idcache_list_free(list);
773 /* Removes servers that are originated from the `from'. The server
774 entry is deleted in this function. If `remove_clients' is TRUE then
775 all clients originated from the server are removed too, and server
776 signoff is sent. Note that this does not remove the `from'. This
777 also does not remove locally connected servers. */
779 void silc_server_remove_servers_by_server(SilcServer server,
780 SilcServerEntry from,
783 SilcIDCacheList list = NULL;
784 SilcIDCacheEntry id_cache = NULL;
785 SilcServerEntry server_entry = NULL;
787 SILC_LOG_DEBUG(("Removing servers by %s",
788 from->server_name ? from->server_name : "server"));
790 if (silc_idcache_get_all(server->local_list->servers, &list)) {
791 if (silc_idcache_list_first(list, &id_cache)) {
793 server_entry = (SilcServerEntry)id_cache->context;
794 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
795 server_entry->router != from || server_entry == from) {
796 if (!silc_idcache_list_next(list, &id_cache))
802 /* Remove clients owned by this server */
804 silc_server_remove_clients_by_server(server, from, server_entry,
807 /* Remove the server */
808 silc_idlist_del_server(server->local_list, server_entry);
810 if (!silc_idcache_list_next(list, &id_cache))
814 silc_idcache_list_free(list);
817 if (silc_idcache_get_all(server->global_list->servers, &list)) {
818 if (silc_idcache_list_first(list, &id_cache)) {
820 server_entry = (SilcServerEntry)id_cache->context;
821 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
822 server_entry->router != from || server_entry == from) {
823 if (!silc_idcache_list_next(list, &id_cache))
829 /* Remove clients owned by this server */
831 silc_server_remove_clients_by_server(server, from, server_entry,
834 /* Remove the server */
835 silc_idlist_del_server(server->global_list, server_entry);
837 if (!silc_idcache_list_next(list, &id_cache))
841 silc_idcache_list_free(list);
845 /* Removes channels that are from `from. */
847 void silc_server_remove_channels_by_server(SilcServer server,
848 SilcServerEntry from)
850 SilcIDCacheList list = NULL;
851 SilcIDCacheEntry id_cache = NULL;
852 SilcChannelEntry channel = NULL;
854 SILC_LOG_DEBUG(("Removing channels by server"));
856 if (silc_idcache_get_all(server->global_list->channels, &list)) {
857 if (silc_idcache_list_first(list, &id_cache)) {
859 channel = (SilcChannelEntry)id_cache->context;
860 if (channel->router == from)
861 silc_idlist_del_channel(server->global_list, channel);
862 if (!silc_idcache_list_next(list, &id_cache))
866 silc_idcache_list_free(list);
870 /* Updates channels that are from `from' to be originated from `to'. */
872 void silc_server_update_channels_by_server(SilcServer server,
873 SilcServerEntry from,
876 SilcIDCacheList list = NULL;
877 SilcIDCacheEntry id_cache = NULL;
878 SilcChannelEntry channel = NULL;
880 SILC_LOG_DEBUG(("Updating channels by server"));
882 if (silc_idcache_get_all(server->global_list->channels, &list)) {
883 if (silc_idcache_list_first(list, &id_cache)) {
885 channel = (SilcChannelEntry)id_cache->context;
886 if (channel->router == from)
887 channel->router = to;
888 if (!silc_idcache_list_next(list, &id_cache))
892 silc_idcache_list_free(list);
896 /* Checks whether given channel has global users. If it does this returns
897 TRUE and FALSE if there is only locally connected clients on the channel. */
899 bool silc_server_channel_has_global(SilcChannelEntry channel)
901 SilcChannelClientEntry chl;
902 SilcHashTableList htl;
904 silc_hash_table_list(channel->user_list, &htl);
905 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
906 if (chl->client->router) {
907 silc_hash_table_list_reset(&htl);
911 silc_hash_table_list_reset(&htl);
916 /* Checks whether given channel has locally connected users. If it does this
917 returns TRUE and FALSE if there is not one locally connected client. */
919 bool silc_server_channel_has_local(SilcChannelEntry channel)
921 SilcChannelClientEntry chl;
922 SilcHashTableList htl;
924 silc_hash_table_list(channel->user_list, &htl);
925 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
926 if (SILC_IS_LOCAL(chl->client)) {
927 silc_hash_table_list_reset(&htl);
931 silc_hash_table_list_reset(&htl);
936 /* This function removes the channel and all users on the channel, unless
937 the channel is permanent. In this case the channel is disabled but all
938 users are removed from the channel. Returns TRUE if the channel is
939 destroyed totally, and FALSE if it is permanent and remains. */
941 bool silc_server_channel_delete(SilcServer server,
942 SilcChannelEntry channel)
944 SilcChannelClientEntry chl;
945 SilcHashTableList htl;
946 bool delchan = !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH);
949 /* Update statistics */
950 if (server->server_type == SILC_ROUTER)
951 server->stat.chanclients -= channel->user_count;
953 /* Totally delete the channel and all users on the channel. The
954 users are deleted automatically in silc_idlist_del_channel. */
955 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
956 if (silc_idlist_del_channel(server->local_list, channel)) {
957 server->stat.my_channels--;
958 if (server->server_type == SILC_ROUTER) {
959 server->stat.channels--;
960 server->stat.cell_channels--;
963 if (silc_idlist_del_channel(server->global_list, channel))
964 if (server->server_type == SILC_ROUTER)
965 server->stat.channels--;
971 /* Channel is permanent, do not remove it, remove only users */
972 channel->disabled = TRUE;
973 silc_hash_table_list(channel->user_list, &htl);
974 while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
975 silc_hash_table_del(chl->client->channels, channel);
976 silc_hash_table_del(channel->user_list, chl->client);
977 channel->user_count--;
979 /* Update statistics */
980 if (SILC_IS_LOCAL(chl->client))
981 server->stat.my_chanclients--;
982 if (server->server_type == SILC_ROUTER) {
983 server->stat.cell_chanclients--;
984 server->stat.chanclients--;
989 silc_hash_table_list_reset(&htl);
991 SILC_LOG_DEBUG(("Channel %s remains", channel->channel_name));
996 /* Returns TRUE if the given client is on the channel. FALSE if not.
997 This works because we assure that the user list on the channel is
998 always in up to date thus we can only check the channel list from
999 `client' which is faster than checking the user list from `channel'. */
1001 bool silc_server_client_on_channel(SilcClientEntry client,
1002 SilcChannelEntry channel,
1003 SilcChannelClientEntry *chl)
1005 if (!client || !channel)
1008 return silc_hash_table_find(client->channels, channel, NULL,
1012 /* Checks string for bad characters and returns TRUE if they are found. */
1014 bool silc_server_name_bad_chars(const char *name, SilcUInt32 name_len)
1018 for (i = 0; i < name_len; i++) {
1019 if (!isascii(name[i]))
1021 if (name[i] <= 32) return TRUE;
1022 if (name[i] == ' ') return TRUE;
1023 if (name[i] == '*') return TRUE;
1024 if (name[i] == '?') return TRUE;
1025 if (name[i] == ',') return TRUE;
1031 /* Modifies the `name' if it includes bad characters and returns new
1032 allocated name that does not include bad characters. */
1034 char *silc_server_name_modify_bad(const char *name, SilcUInt32 name_len)
1037 char *newname = strdup(name);
1039 for (i = 0; i < name_len; i++) {
1040 if (!isascii(newname[i])) newname[i] = '_';
1041 if (newname[i] <= 32) newname[i] = '_';
1042 if (newname[i] == ' ') newname[i] = '_';
1043 if (newname[i] == '*') newname[i] = '_';
1044 if (newname[i] == '?') newname[i] = '_';
1045 if (newname[i] == ',') newname[i] = '_';
1051 /* Find number of sockets by IP address indicated by `ip'. Returns 0 if
1052 socket connections with the IP address does not exist. */
1054 SilcUInt32 silc_server_num_sockets_by_ip(SilcServer server, const char *ip,
1055 SilcSocketType type)
1059 for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
1060 if (server->sockets[i] && !SILC_IS_LISTENER(server->sockets[i]) &&
1061 !strcmp(server->sockets[i]->ip, ip) &&
1062 server->sockets[i]->type == type)
1069 /* Find number of sockets by IP address indicated by remote host, indicatd
1070 by `ip' or `hostname', `port', and `type'. Returns 0 if socket connections
1071 does not exist. If `ip' is provided then `hostname' is ignored. */
1073 SilcUInt32 silc_server_num_sockets_by_remote(SilcServer server,
1075 const char *hostname,
1077 SilcSocketType type)
1081 if (!ip && !hostname)
1084 for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
1085 if (server->sockets[i] && !SILC_IS_LISTENER(server->sockets[i]) &&
1086 ((ip && !strcmp(server->sockets[i]->ip, ip)) ||
1087 (hostname && !strcmp(server->sockets[i]->hostname, hostname))) &&
1088 server->sockets[i]->port == port &&
1089 server->sockets[i]->type == type)
1096 /* Finds locally cached public key by the public key received in the SKE.
1097 If we have it locally cached then we trust it and will use it in the
1098 authentication protocol. Returns the locally cached public key or NULL
1099 if we do not find the public key. */
1101 SilcPublicKey silc_server_find_public_key(SilcServer server,
1102 SilcHashTable local_public_keys,
1103 SilcPublicKey remote_public_key)
1105 SilcPublicKey cached_key;
1107 SILC_LOG_DEBUG(("Find remote public key (%d keys in local cache)",
1108 silc_hash_table_count(local_public_keys)));
1110 if (!silc_hash_table_find_ext(local_public_keys, remote_public_key,
1111 (void **)&cached_key, NULL,
1112 silc_hash_public_key, NULL,
1113 silc_hash_public_key_compare, NULL)) {
1114 SILC_LOG_ERROR(("Public key not found"));
1118 SILC_LOG_DEBUG(("Found public key"));
1123 /* This returns the first public key from the table of public keys. This
1124 is used only in cases where single public key exists in the table and
1125 we want to get a pointer to it. For public key tables that has multiple
1126 keys in it the silc_server_find_public_key must be used. */
1128 SilcPublicKey silc_server_get_public_key(SilcServer server,
1129 SilcHashTable local_public_keys)
1131 SilcPublicKey cached_key;
1132 SilcHashTableList htl;
1134 SILC_LOG_DEBUG(("Start"));
1136 assert(silc_hash_table_count(local_public_keys) < 2);
1138 silc_hash_table_list(local_public_keys, &htl);
1139 if (!silc_hash_table_get(&htl, NULL, (void **)&cached_key))
1141 silc_hash_table_list_reset(&htl);
1146 /* Check whether the connection `sock' is allowed to connect to us. This
1147 checks for example whether there is too much connections for this host,
1148 and required version for the host etc. */
1150 bool silc_server_connection_allowed(SilcServer server,
1151 SilcSocketConnection sock,
1152 SilcSocketType type,
1153 SilcServerConfigConnParams *global,
1154 SilcServerConfigConnParams *params,
1157 SilcUInt32 conn_number = (type == SILC_SOCKET_TYPE_CLIENT ?
1158 server->stat.my_clients :
1159 type == SILC_SOCKET_TYPE_SERVER ?
1160 server->stat.my_servers :
1161 server->stat.my_routers);
1162 SilcUInt32 num_sockets, max_hosts, max_per_host;
1163 SilcUInt32 r_protocol_version, l_protocol_version;
1164 SilcUInt32 r_software_version, l_software_version;
1165 char *r_vendor_version = NULL, *l_vendor_version;
1167 SILC_LOG_DEBUG(("Checking whether connection is allowed"));
1171 l_protocol_version =
1172 silc_version_to_num(params && params->version_protocol ?
1173 params->version_protocol :
1174 global->version_protocol);
1175 l_software_version =
1176 silc_version_to_num(params && params->version_software ?
1177 params->version_software :
1178 global->version_software);
1179 l_vendor_version = (params && params->version_software_vendor ?
1180 params->version_software_vendor :
1181 global->version_software_vendor);
1183 if (ske && silc_ske_parse_version(ske, &r_protocol_version, NULL,
1184 &r_software_version, NULL,
1185 &r_vendor_version)) {
1186 sock->version = r_protocol_version;
1188 /* Match protocol version */
1189 if (l_protocol_version && r_protocol_version &&
1190 r_protocol_version < l_protocol_version) {
1191 SILC_LOG_INFO(("Connection %s (%s) is too old version",
1192 sock->hostname, sock->ip));
1193 silc_server_disconnect_remote(server, sock,
1194 SILC_STATUS_ERR_BAD_VERSION,
1195 "You support too old protocol version");
1199 /* Math software version */
1200 if (l_software_version && r_software_version &&
1201 r_software_version < l_software_version) {
1202 SILC_LOG_INFO(("Connection %s (%s) is too old version",
1203 sock->hostname, sock->ip));
1204 silc_server_disconnect_remote(server, sock,
1205 SILC_STATUS_ERR_BAD_VERSION,
1206 "You support too old software version");
1210 /* Regex match vendor version */
1211 if (l_vendor_version && r_vendor_version &&
1212 !silc_string_match(l_vendor_version, r_vendor_version)) {
1213 SILC_LOG_INFO(("Connection %s (%s) is unsupported version",
1214 sock->hostname, sock->ip));
1215 silc_server_disconnect_remote(server, sock,
1216 SILC_STATUS_ERR_BAD_VERSION,
1217 "Your software is not supported");
1221 silc_free(r_vendor_version);
1223 /* Check for maximum connections limit */
1225 num_sockets = silc_server_num_sockets_by_ip(server, sock->ip, type);
1226 max_hosts = (params ? params->connections_max : global->connections_max);
1227 max_per_host = (params ? params->connections_max_per_host :
1228 global->connections_max_per_host);
1230 if (max_hosts && conn_number >= max_hosts) {
1231 SILC_LOG_INFO(("Server is full, closing %s (%s) connection",
1232 sock->hostname, sock->ip));
1233 silc_server_disconnect_remote(server, sock,
1234 SILC_STATUS_ERR_RESOURCE_LIMIT,
1235 "Server is full, try again later");
1239 if (num_sockets >= max_per_host) {
1240 SILC_LOG_INFO(("Too many connections from %s (%s), closing connection",
1241 sock->hostname, sock->ip));
1242 silc_server_disconnect_remote(server, sock,
1243 SILC_STATUS_ERR_RESOURCE_LIMIT,
1244 "Too many connections from your host");
1251 /* Checks that client has rights to add or remove channel modes. If any
1252 of the checks fails FALSE is returned. */
1254 bool silc_server_check_cmode_rights(SilcServer server,
1255 SilcChannelEntry channel,
1256 SilcChannelClientEntry client,
1259 bool is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1260 bool is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1262 /* Check whether has rights to change anything */
1263 if (!is_op && !is_fo)
1266 /* Check whether has rights to change everything */
1270 /* Founder implies operator */
1274 /* We know that client is channel operator, check that they are not
1275 changing anything that requires channel founder rights. Rest of the
1276 modes are available automatically for channel operator. */
1278 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1279 if (is_op && !is_fo)
1282 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1283 if (is_op && !is_fo)
1288 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1289 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
1290 if (is_op && !is_fo)
1294 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1295 if (is_op && !is_fo)
1300 if (mode & SILC_CHANNEL_MODE_CIPHER) {
1301 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
1302 if (is_op && !is_fo)
1306 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1307 if (is_op && !is_fo)
1312 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1313 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
1314 if (is_op && !is_fo)
1318 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1319 if (is_op && !is_fo)
1324 if (mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1325 if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS)) {
1326 if (is_op && !is_fo)
1330 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1331 if (is_op && !is_fo)
1336 if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1337 if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS)) {
1338 if (is_op && !is_fo)
1342 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1343 if (is_op && !is_fo)
1351 /* Check that the client has rights to change its user mode. Returns
1352 FALSE if setting some mode is not allowed. */
1354 bool silc_server_check_umode_rights(SilcServer server,
1355 SilcClientEntry client,
1358 bool server_op = FALSE, router_op = FALSE;
1360 if (mode & SILC_UMODE_SERVER_OPERATOR) {
1361 /* Cannot set server operator mode (must use OPER command) */
1362 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR))
1365 /* Remove the server operator rights */
1366 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
1370 if (mode & SILC_UMODE_ROUTER_OPERATOR) {
1371 /* Cannot set router operator mode (must use SILCOPER command) */
1372 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR))
1375 /* Remove the router operator rights */
1376 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
1381 SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR);
1383 SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR);
1388 /* This function is used to send the notify packets and motd to the
1389 incoming client connection. */
1391 void silc_server_send_connect_notifys(SilcServer server,
1392 SilcSocketConnection sock,
1393 SilcClientEntry client)
1395 SilcIDListData idata = (SilcIDListData)client;
1397 SILC_LOG_DEBUG(("Send welcome notifys"));
1399 /* Send some nice info to the client */
1400 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1401 ("Welcome to the SILC Network %s",
1403 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1404 ("Your host is %s, running version %s",
1405 server->server_name, server_version));
1407 if (server->server_type == SILC_ROUTER) {
1408 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1409 ("There are %d clients, %d servers and %d "
1410 "routers in SILC Network",
1411 server->stat.clients, server->stat.servers + 1,
1412 server->stat.routers));
1414 if (server->stat.clients && server->stat.servers + 1)
1415 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1416 ("There are %d clients, %d servers and %d "
1417 "routers in SILC Network",
1418 server->stat.clients, server->stat.servers + 1,
1419 (server->standalone ? 0 :
1420 !server->stat.routers ? 1 :
1421 server->stat.routers)));
1424 if (server->stat.cell_clients && server->stat.cell_servers + 1)
1425 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1426 ("There are %d clients on %d server in our cell",
1427 server->stat.cell_clients,
1428 server->stat.cell_servers + 1));
1429 if (server->server_type == SILC_ROUTER) {
1430 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1431 ("I have %d clients, %d channels, %d servers and "
1433 server->stat.my_clients,
1434 server->stat.my_channels,
1435 server->stat.my_servers,
1436 server->stat.my_routers));
1438 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1439 ("I have %d clients and %d channels formed",
1440 server->stat.my_clients,
1441 server->stat.my_channels));
1444 if (server->stat.server_ops || server->stat.router_ops)
1445 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1446 ("There are %d server operators and %d router "
1448 server->stat.server_ops,
1449 server->stat.router_ops));
1450 if (server->stat.my_router_ops + server->stat.my_server_ops)
1451 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1452 ("I have %d operators online",
1453 server->stat.my_router_ops +
1454 server->stat.my_server_ops));
1456 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1457 ("Your connection is secured with %s cipher, "
1458 "key length %d bits",
1459 silc_cipher_get_name(idata->send_key),
1460 silc_cipher_get_key_len(idata->send_key)));
1461 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1462 ("Your current nickname is %s",
1466 silc_server_send_motd(server, sock);
1469 /* Kill the client indicated by `remote_client' sending KILLED notify
1470 to the client, to all channels client has joined and to primary
1471 router if needed. The killed client is also removed from all channels. */
1473 void silc_server_kill_client(SilcServer server,
1474 SilcClientEntry remote_client,
1475 const char *comment,
1477 SilcIdType killer_id_type)
1479 SilcBuffer killed, killer;
1481 SILC_LOG_DEBUG(("Killing client %s",
1482 silc_id_render(remote_client->id, SILC_ID_CLIENT)));
1484 /* Send the KILL notify packets. First send it to the channel, then
1485 to our primary router and then directly to the client who is being
1486 killed right now. */
1488 killed = silc_id_payload_encode(remote_client->id, SILC_ID_CLIENT);
1489 killer = silc_id_payload_encode(killer_id, killer_id_type);
1491 /* Send KILLED notify to the channels. It is not sent to the client
1492 as it will be sent differently destined directly to the client and not
1494 silc_server_send_notify_on_channels(server, remote_client,
1495 remote_client, SILC_NOTIFY_TYPE_KILLED,
1496 3, killed->data, killed->len,
1497 comment, comment ? strlen(comment) : 0,
1498 killer->data, killer->len);
1500 /* Send KILLED notify to primary route */
1501 silc_server_send_notify_killed(server, SILC_PRIMARY_ROUTE(server),
1502 SILC_BROADCAST(server), remote_client->id,
1503 comment, killer_id, killer_id_type);
1505 /* Send KILLED notify to the client directly */
1506 if (remote_client->connection || remote_client->router)
1507 silc_server_send_notify_killed(server, remote_client->connection ?
1508 remote_client->connection :
1509 remote_client->router->connection, FALSE,
1510 remote_client->id, comment,
1511 killer_id, killer_id_type);
1513 /* Remove the client from all channels. This generates new keys to the
1514 channels as well. */
1515 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
1518 /* Remove the client entry, If it is locally connected then we will also
1519 disconnect the client here */
1520 if (remote_client->connection) {
1521 /* Remove locally conneted client */
1522 SilcSocketConnection sock = remote_client->connection;
1523 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
1524 silc_server_close_connection(server, sock);
1526 /* Update statistics */
1527 server->stat.clients--;
1528 if (server->stat.cell_clients)
1529 server->stat.cell_clients--;
1530 SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
1531 SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
1533 if (SILC_IS_LOCAL(remote_client)) {
1534 server->stat.my_clients--;
1535 silc_schedule_task_del_by_context(server->schedule, remote_client);
1536 silc_idlist_del_data(remote_client);
1539 /* Remove remote client */
1540 silc_idlist_del_data(remote_client);
1541 if (!silc_idlist_del_client(server->global_list, remote_client)) {
1542 /* Remove this client from watcher list if it is */
1543 silc_server_del_from_watcher_list(server, remote_client);
1544 silc_idlist_del_client(server->local_list, remote_client);
1548 silc_buffer_free(killer);
1549 silc_buffer_free(killed);
1554 SilcClientEntry client;
1555 SilcNotifyType notify;
1556 const char *new_nick;
1557 } WatcherNotifyContext;
1560 silc_server_check_watcher_list_foreach(void *key, void *context,
1563 WatcherNotifyContext *notify = user_context;
1564 SilcClientEntry entry = context;
1565 SilcSocketConnection sock;
1570 if (entry == notify->client)
1573 sock = silc_server_get_client_route(notify->server, NULL, 0, entry->id,
1576 SILC_LOG_DEBUG(("Sending WATCH notify to %s",
1577 silc_id_render(entry->id, SILC_ID_CLIENT)));
1579 /* Send the WATCH notify */
1580 silc_server_send_notify_watch(notify->server, sock, entry,
1582 notify->new_nick ? notify->new_nick :
1583 (const char *)notify->client->nickname,
1588 /* This function checks whether the `client' nickname is being watched
1589 by someone, and notifies the watcher of the notify change of notify
1590 type indicated by `notify'. */
1592 bool silc_server_check_watcher_list(SilcServer server,
1593 SilcClientEntry client,
1594 const char *new_nick,
1595 SilcNotifyType notify)
1597 unsigned char hash[16];
1598 WatcherNotifyContext n;
1600 SILC_LOG_DEBUG(("Checking watcher list %s",
1601 client->nickname ? client->nickname : (unsigned char *)""));
1603 /* If the watching is rejected by the client do nothing */
1604 if (client->mode & SILC_UMODE_REJECT_WATCHING)
1607 /* Make hash from the nick, or take it from Client ID */
1608 if (client->nickname) {
1610 memset(nick, 0, sizeof(nick));
1611 silc_to_lower(client->nickname, nick, sizeof(nick) - 1);
1612 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
1614 memset(hash, 0, sizeof(hash));
1615 memcpy(hash, client->id->hash, sizeof(client->id->hash));
1620 n.new_nick = new_nick;
1623 /* Send notify to all watchers */
1624 silc_hash_table_find_foreach(server->watcher_list, hash,
1625 silc_server_check_watcher_list_foreach, &n);
1630 /* Remove the `client' from watcher list. After calling this the `client'
1631 is not watching any nicknames. */
1633 bool silc_server_del_from_watcher_list(SilcServer server,
1634 SilcClientEntry client)
1636 SilcHashTableList htl;
1638 SilcClientEntry entry;
1641 silc_hash_table_list(server->watcher_list, &htl);
1642 while (silc_hash_table_get(&htl, &key, (void **)&entry)) {
1643 if (entry == client) {
1644 silc_hash_table_del_by_context(server->watcher_list, key, client);
1647 SILC_LOG_DEBUG(("Removing %s from WATCH list",
1648 silc_id_render(client->id, SILC_ID_CLIENT)));
1650 /* Now check whether there still exists entries with this key, if not
1651 then free the key to not leak memory. */
1652 if (!silc_hash_table_find(server->watcher_list, key, NULL, NULL))
1658 silc_hash_table_list_reset(&htl);
1663 /* Force the client indicated by `chl' to change the channel user mode
1664 on channel indicated by `channel' to `forced_mode'. */
1666 bool silc_server_force_cumode_change(SilcServer server,
1667 SilcSocketConnection sock,
1668 SilcChannelEntry channel,
1669 SilcChannelClientEntry chl,
1670 SilcUInt32 forced_mode)
1672 SilcBuffer idp1, idp2;
1673 unsigned char cumode[4];
1675 SILC_LOG_DEBUG(("Enforcing sender to change mode"));
1678 silc_server_send_notify_cumode(server, sock, FALSE, channel, forced_mode,
1679 server->id, SILC_ID_SERVER,
1680 chl->client->id, NULL);
1682 idp1 = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1683 idp2 = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
1684 SILC_PUT32_MSB(forced_mode, cumode);
1685 silc_server_send_notify_to_channel(server, sock, channel, FALSE,
1686 SILC_NOTIFY_TYPE_CUMODE_CHANGE,
1687 3, idp1->data, idp1->len,
1688 cumode, sizeof(cumode),
1689 idp2->data, idp2->len);
1690 silc_buffer_free(idp1);
1691 silc_buffer_free(idp2);
1696 /* Find active socket connection by the IP address and port indicated by
1697 `ip' and `port', and socket connection type of `type'. */
1699 SilcSocketConnection
1700 silc_server_find_socket_by_host(SilcServer server,
1701 SilcSocketType type,
1702 const char *ip, SilcUInt16 port)
1706 for (i = 0; i < server->config->param.connections_max; i++) {
1707 if (!server->sockets[i])
1709 if (!strcmp(server->sockets[i]->ip, ip) &&
1710 (!port || server->sockets[i]->port == port) &&
1711 server->sockets[i]->type == type)
1712 return server->sockets[i];
1718 /* This function can be used to match the invite and ban lists. */
1720 bool silc_server_inviteban_match(SilcServer server, SilcHashTable list,
1721 SilcUInt8 type, void *check)
1723 unsigned char *tmp = NULL;
1724 SilcUInt32 len = 0, t;
1725 SilcHashTableList htl;
1729 if (type < 1 || type > 3 || !check)
1733 tmp = strdup((char *)check);
1738 tmp = silc_pkcs_public_key_encode(check, &len);
1743 tmp = silc_id_id2str(check, SILC_ID_CLIENT);
1746 len = silc_id_get_len(check, SILC_ID_CLIENT);
1749 /* Compare the list */
1750 silc_hash_table_list(list, &htl);
1751 while (silc_hash_table_get(&htl, (void **)&t, (void **)&entry)) {
1754 if (silc_string_match((char *)entry, tmp)) {
1758 } else if (!memcmp(entry->data, tmp, len)) {
1764 silc_hash_table_list_reset(&htl);
1770 /* Process invite or ban information */
1772 void silc_server_inviteban_process(SilcServer server, SilcHashTable list,
1773 SilcUInt8 action, SilcArgumentPayload args)
1776 SilcUInt32 type, len;
1778 SilcHashTableList htl;
1780 SILC_LOG_DEBUG(("Processing invite/ban for %s action",
1781 action == 0x00 ? "ADD" : "DEL"));
1783 /* Add the information to invite list */
1784 if (action == 0x00) {
1785 /* Traverse all arguments and add to the hash table according to
1787 tmp = silc_argument_get_first_arg(args, &type, &len);
1790 /* Invite string. Get the old invite string from hash table
1791 and append this at the end of the existing one. */
1792 char *string = NULL;
1793 silc_hash_table_find(list, (void *)1,
1794 NULL, (void **)&string);
1795 silc_hash_table_del(list, (void *)1);
1797 string = silc_calloc(len + 2, sizeof(*string));
1799 string = silc_realloc(string, sizeof(*string) *
1800 (strlen(string) + len + 2));
1801 memset(string + strlen(string), 0, len + 2);
1802 if (tmp[len - 1] == ',')
1803 tmp[len - 1] = '\0';
1804 strncat(string, tmp, len);
1805 strncat(string, ",", 1);
1807 /* Add new invite string to invite list */
1808 silc_hash_table_add(list, (void *)1, string);
1810 } else if (type == 2) {
1811 /* Public key. Check first if the public key is already on the
1812 list and ignore it if it is, otherwise, add it to hash table. */
1814 /* Check if the public key is in the list already */
1815 silc_hash_table_list(list, &htl);
1816 while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
1817 if (type == 2 && !memcmp(tmp2->data, tmp, len)) {
1822 silc_hash_table_list_reset(&htl);
1824 /* Add new public key to invite list */
1826 tmp2 = silc_buffer_alloc_size(len);
1827 silc_buffer_put(tmp2, tmp, len);
1828 silc_hash_table_add(list, (void *)2, tmp2);
1831 } else if (type == 3) {
1834 /* Check if the ID is in the list already */
1835 silc_hash_table_list(list, &htl);
1836 while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
1837 if (type == 3 && !memcmp(tmp2->data, tmp, len)) {
1842 silc_hash_table_list_reset(&htl);
1844 /* Add new Client ID to invite list */
1846 tmp2 = silc_buffer_alloc_size(len);
1847 silc_buffer_put(tmp2, tmp, len);
1848 silc_hash_table_add(list, (void *)3, tmp2);
1852 tmp = silc_argument_get_next_arg(args, &type, &len);
1856 /* Delete information to invite list */
1857 if (action && list) {
1858 /* Now delete the arguments from invite list */
1859 tmp = silc_argument_get_first_arg(args, &type, &len);
1862 /* Invite string. Get the old string from hash table and delete
1863 the requested string. */
1864 char *string = NULL, *start, *end, *n;
1866 if (silc_hash_table_find(list, (void *)1, NULL, (void **)&string)) {
1867 silc_hash_table_del(list, (void *)1);
1869 if (!strncmp(string, tmp, strlen(string) - 1)) {
1873 start = strstr(string, tmp);
1874 if (start && strlen(start) >= len) {
1876 n = silc_calloc(strlen(string) - len, sizeof(*n));
1877 strncat(n, string, start - string);
1878 strncat(n, end + 1, ((string + strlen(string)) - end) - 1);
1884 /* Add new invite string to invite list */
1886 silc_hash_table_add(list, (void *)1, string);
1889 } else if (type == 2) {
1892 /* Delete from the invite list */
1893 silc_hash_table_list(list, &htl);
1894 while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
1895 if (type == 2 && !memcmp(tmp2->data, tmp, len)) {
1896 silc_hash_table_del_by_context(list, (void *)2, tmp2);
1897 silc_buffer_free(tmp2);
1901 silc_hash_table_list_reset(&htl);
1903 } else if (type == 3) {
1906 /* Delete from the invite list */
1907 silc_hash_table_list(list, &htl);
1908 while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
1909 if (type == 2 && !memcmp(tmp2->data, tmp, len)) {
1910 silc_hash_table_del_by_context(list, (void *)2, tmp2);
1911 silc_buffer_free(tmp2);
1915 silc_hash_table_list_reset(&htl);
1918 tmp = silc_argument_get_next_arg(args, &type, &len);