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 %s from all channels",
46 client->nickname ? client->nickname : ""));
48 if (silc_hash_table_find(clients, client, NULL, NULL))
49 silc_hash_table_del(clients, client);
51 /* Remove the client from all channels. The client is removed from
52 the channels' user list. */
53 silc_hash_table_list(client->channels, &htl);
54 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
55 channel = chl->channel;
57 /* Remove channel if this is last client leaving the channel, unless
58 the channel is permanent. */
59 if (server->server_type != SILC_SERVER &&
60 silc_hash_table_count(channel->user_list) < 2) {
61 if (silc_hash_table_find(channels, channel, NULL, NULL))
62 silc_hash_table_del(channels, channel);
63 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
64 silc_server_channel_delete(server, channel);
68 silc_hash_table_del(client->channels, channel);
69 silc_hash_table_del(channel->user_list, chl->client);
70 channel->user_count--;
72 /* If there is no global users on the channel anymore mark the channel
73 as local channel. Do not check if the removed client is local client. */
74 if (server->server_type != SILC_ROUTER && channel->global_users &&
75 chl->client->router && !silc_server_channel_has_global(channel))
76 channel->global_users = FALSE;
80 /* Update statistics */
81 if (SILC_IS_LOCAL(client))
82 server->stat.my_chanclients--;
83 if (server->server_type == SILC_ROUTER) {
84 server->stat.cell_chanclients--;
85 server->stat.chanclients--;
88 /* If there is not at least one local user on the channel then we don't
89 need the channel entry anymore, we can remove it safely, unless the
90 channel is permanent channel */
91 if (server->server_type == SILC_SERVER &&
92 !silc_server_channel_has_local(channel)) {
93 if (silc_hash_table_find(channels, channel, NULL, NULL))
94 silc_hash_table_del(channels, channel);
95 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
96 silc_server_channel_delete(server, channel);
100 /* Mark other local clients to the table of clients whom will receive
101 the SERVER_SIGNOFF notify. */
102 silc_hash_table_list(channel->user_list, &htl2);
103 while (silc_hash_table_get(&htl2, NULL, (void **)&chl2)) {
104 SilcClientEntry c = chl2->client;
108 /* Add client to table, if it's not from the signoff server */
109 if (c->router != server_entry &&
110 !silc_hash_table_find(clients, c, NULL, NULL))
111 silc_hash_table_add(clients, c, c);
113 silc_hash_table_list_reset(&htl2);
115 /* Add the channel to the the channels list to regenerate the
117 if (!silc_hash_table_find(channels, channel, NULL, NULL))
118 silc_hash_table_add(channels, channel, channel);
120 silc_hash_table_list_reset(&htl);
123 /* This function removes all client entries that are originated from
124 `router' and are owned by `entry'. `router' and `entry' can be same
125 too. If `server_signoff' is TRUE then SERVER_SIGNOFF notify is
126 distributed to our local clients. */
128 bool silc_server_remove_clients_by_server(SilcServer server,
129 SilcServerEntry router,
130 SilcServerEntry entry,
133 SilcIDCacheList list = NULL;
134 SilcIDCacheEntry id_cache = NULL;
135 SilcClientEntry client = NULL;
137 unsigned char **argv = NULL;
138 SilcUInt32 *argv_lens = NULL, *argv_types = NULL, argc = 0;
139 SilcHashTableList htl;
140 SilcChannelEntry channel;
141 SilcHashTable channels, clients;
144 if (!(entry->data.status & SILC_IDLIST_STATUS_REGISTERED))
147 SILC_LOG_DEBUG(("Removing clients by %s",
148 entry->server_name ? entry->server_name : "server"));
153 /* Allocate the hash table that holds the channels that require
154 channel key re-generation after we've removed this server's clients
155 from the channels. */
156 channels = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL,
158 clients = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL,
161 if (server_signoff) {
162 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
163 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
164 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) * (argc + 1));
165 argv_types = silc_realloc(argv_types, sizeof(*argv_types) * (argc + 1));
166 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
167 memcpy(argv[argc], idp->data, idp->len);
168 argv_lens[argc] = idp->len;
169 argv_types[argc] = argc + 1;
171 silc_buffer_free(idp);
174 if (silc_idcache_get_all(server->local_list->clients, &list)) {
175 if (silc_idcache_list_first(list, &id_cache)) {
177 client = (SilcClientEntry)id_cache->context;
179 /* If client is not registered, is not originated from `router'
180 and is not owned by `entry', skip it. */
181 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
182 client->router != router ||
183 (router != entry && !SILC_ID_COMPARE(client->id, entry->id,
184 client->id->ip.data_len))) {
185 if (!silc_idcache_list_next(list, &id_cache))
191 if (server_signoff) {
192 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
193 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
194 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
196 argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
198 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
199 memcpy(argv[argc], idp->data, idp->len);
200 argv_lens[argc] = idp->len;
201 argv_types[argc] = argc + 1;
203 silc_buffer_free(idp);
206 /* Update statistics */
207 server->stat.clients--;
208 if (server->stat.cell_clients)
209 server->stat.cell_clients--;
210 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
211 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
213 silc_server_remove_clients_channels(server, entry, clients,
215 silc_server_del_from_watcher_list(server, client);
217 /* Remove the client entry */
218 if (!server_signoff) {
219 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
220 id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
222 silc_idlist_del_data(client);
223 silc_idlist_del_client(server->local_list, client);
226 if (!silc_idcache_list_next(list, &id_cache))
230 silc_idcache_list_free(list);
233 if (silc_idcache_get_all(server->global_list->clients, &list)) {
235 if (silc_idcache_list_first(list, &id_cache)) {
237 client = (SilcClientEntry)id_cache->context;
239 /* If client is not registered, is not originated from `router'
240 and is not owned by `entry', skip it. */
241 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
242 client->router != router ||
243 (router != entry && !SILC_ID_COMPARE(client->id, entry->id,
244 client->id->ip.data_len))) {
245 if (!silc_idcache_list_next(list, &id_cache))
251 if (server_signoff) {
252 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
253 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
254 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
256 argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
258 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
259 memcpy(argv[argc], idp->data, idp->len);
260 argv_lens[argc] = idp->len;
261 argv_types[argc] = argc + 1;
263 silc_buffer_free(idp);
266 /* Update statistics */
267 server->stat.clients--;
268 if (server->stat.cell_clients)
269 server->stat.cell_clients--;
270 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
271 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
273 silc_server_remove_clients_channels(server, entry, clients,
275 silc_server_del_from_watcher_list(server, client);
277 /* Remove the client entry */
278 if (!server_signoff) {
279 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
280 id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
282 silc_idlist_del_data(client);
283 silc_idlist_del_client(server->global_list, client);
286 if (!silc_idcache_list_next(list, &id_cache))
290 silc_idcache_list_free(list);
293 /* Return now if we are shutting down */
294 if (server->server_shutdown) {
295 silc_hash_table_free(channels);
297 if (server_signoff) {
298 for (i = 0; i < argc; i++)
301 silc_free(argv_lens);
302 silc_free(argv_types);
303 silc_hash_table_free(clients);
308 /* Send the SERVER_SIGNOFF notify */
309 if (server_signoff) {
310 SilcBuffer args, not;
312 SILC_LOG_DEBUG(("Sending SERVER_SIGNOFF for %s with %d clients",
313 silc_id_render(entry->id, SILC_ID_SERVER), argc - 1));
315 /* Send SERVER_SIGNOFF notify to our primary router */
316 if (server->router != entry) {
317 args = silc_argument_payload_encode(1, argv, argv_lens,
319 silc_server_send_notify_args(server, SILC_PRIMARY_ROUTE(server),
320 SILC_BROADCAST(server),
321 SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
323 silc_buffer_free(args);
326 /* Send to local clients. We also send the list of client ID's that
327 is to be removed for those servers that would like to use that list. */
328 args = silc_argument_payload_encode(argc, argv, argv_lens,
330 not = silc_notify_payload_encode_args(SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
332 silc_server_packet_send_clients(server, clients,
333 SILC_PACKET_NOTIFY, 0, FALSE,
334 not->data, not->len, FALSE);
336 /* Send notify also to local backup routers */
337 silc_server_backup_send(server, NULL, SILC_PACKET_NOTIFY, 0,
338 not->data, not->len, FALSE, TRUE);
340 silc_buffer_free(args);
341 silc_buffer_free(not);
342 for (i = 0; i < argc; i++)
345 silc_free(argv_lens);
346 silc_free(argv_types);
347 silc_hash_table_free(clients);
350 /* We must now re-generate the channel key for all channels that had
351 this server's client(s) on the channel. As they left the channel we
352 must re-generate the channel key. */
353 silc_hash_table_list(channels, &htl);
354 while (silc_hash_table_get(&htl, NULL, (void **)&channel)) {
355 if (!silc_server_create_channel_key(server, channel, 0)) {
356 silc_hash_table_list_reset(&htl);
357 silc_hash_table_free(channels);
361 /* Do not send the channel key if private channel key mode is set */
362 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY || !channel->channel_key)
365 silc_server_send_channel_key(server, NULL, channel,
366 server->server_type == SILC_ROUTER ?
367 FALSE : !server->standalone);
369 silc_hash_table_list_reset(&htl);
370 silc_hash_table_free(channels);
375 static SilcServerEntry
376 silc_server_update_clients_by_real_server(SilcServer server,
377 SilcServerEntry from,
379 SilcClientEntry client,
381 SilcIDCacheEntry client_cache)
383 SilcServerEntry server_entry;
384 SilcIDCacheEntry id_cache = NULL;
385 SilcIDCacheList list;
386 bool tolocal = (to == server->id_entry);
388 if (!silc_idcache_get_all(server->local_list->servers, &list))
391 if (silc_idcache_list_first(list, &id_cache)) {
393 server_entry = (SilcServerEntry)id_cache->context;
394 if (server_entry != from &&
395 (tolocal || server_entry != server->id_entry) &&
396 SILC_ID_COMPARE(server_entry->id, client->id,
397 client->id->ip.data_len)) {
398 SILC_LOG_DEBUG(("Found (local) %s",
399 silc_id_render(server_entry->id, SILC_ID_SERVER)));
401 if (!server_entry->data.send_key && server_entry->router) {
402 SILC_LOG_DEBUG(("Server not locally connected, use its router"));
403 /* If the client is not marked as local then move it to local list
404 since the server is local. */
406 SILC_LOG_DEBUG(("Moving client to local list"));
407 silc_idcache_add(server->local_list->clients, client_cache->name,
408 client_cache->id, client_cache->context,
409 client_cache->expire, NULL);
410 silc_idcache_del_by_context(server->global_list->clients, client);
412 server_entry = server_entry->router;
414 /* If the client is not marked as local then move it to local list
415 since the server is local. */
416 if (server_entry->server_type != SILC_BACKUP_ROUTER && !local) {
417 SILC_LOG_DEBUG(("Moving client to local list"));
418 silc_idcache_add(server->local_list->clients, client_cache->name,
419 client_cache->id, client_cache->context,
420 client_cache->expire, NULL);
421 silc_idcache_del_by_context(server->global_list->clients, client);
425 silc_idcache_list_free(list);
429 if (!silc_idcache_list_next(list, &id_cache))
434 silc_idcache_list_free(list);
436 if (!silc_idcache_get_all(server->global_list->servers, &list))
439 if (silc_idcache_list_first(list, &id_cache)) {
441 server_entry = (SilcServerEntry)id_cache->context;
442 if (server_entry != from && server_entry != server->id_entry &&
443 (tolocal || server_entry != server->id_entry) &&
444 SILC_ID_COMPARE(server_entry->id, client->id,
445 client->id->ip.data_len)) {
446 SILC_LOG_DEBUG(("Found (global) %s",
447 silc_id_render(server_entry->id, SILC_ID_SERVER)));
449 if (!server_entry->data.send_key && server_entry->router) {
450 SILC_LOG_DEBUG(("Server not locally connected, use its router"));
451 /* If the client is marked as local then move it to global list
452 since the server is global. */
454 SILC_LOG_DEBUG(("Moving client to global list"));
455 silc_idcache_add(server->global_list->clients, client_cache->name,
456 client_cache->id, client_cache->context, 0, NULL);
457 silc_idcache_del_by_context(server->local_list->clients, client);
459 server_entry = server_entry->router;
461 /* If the client is marked as local then move it to global list
462 since the server is global. */
463 if (server_entry->server_type != SILC_BACKUP_ROUTER && local) {
464 SILC_LOG_DEBUG(("Moving client to global list"));
465 silc_idcache_add(server->global_list->clients, client_cache->name,
466 client_cache->id, client_cache->context, 0, NULL);
467 silc_idcache_del_by_context(server->local_list->clients, client);
471 silc_idcache_list_free(list);
475 if (!silc_idcache_list_next(list, &id_cache))
480 silc_idcache_list_free(list);
485 /* Updates the clients that are originated from the `from' to be originated
486 from the `to'. If the `resolve_real_server' is TRUE then this will
487 attempt to figure out which clients really are originated from the
488 `from' and which are originated from a server that we have connection
489 to, when we've acting as backup router. If it is FALSE the `to' will
490 be the new source. */
492 void silc_server_update_clients_by_server(SilcServer server,
493 SilcServerEntry from,
495 bool resolve_real_server)
497 SilcIDCacheList list = NULL;
498 SilcIDCacheEntry id_cache = NULL;
499 SilcClientEntry client = NULL;
503 if (silc_idcache_get_all(server->global_list->clients, &list)) {
504 if (silc_idcache_list_first(list, &id_cache)) {
506 client = (SilcClientEntry)id_cache->context;
508 /* If entry is disabled skip it. If entry is local to us, do not
509 switch it to anyone else, it is ours so skip it. */
510 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
511 SILC_IS_LOCAL(client)) {
512 if (!silc_idcache_list_next(list, &id_cache))
518 SILC_LOG_DEBUG(("Client %s",
519 silc_id_render(client->id, SILC_ID_CLIENT)));
521 SILC_LOG_DEBUG(("Client->router %s",
522 silc_id_render(client->router->id, SILC_ID_SERVER)));
525 if (client->router == from) {
526 if (resolve_real_server) {
528 silc_server_update_clients_by_real_server(server, from, to,
531 if (!client->router) {
532 if (server->server_type == SILC_ROUTER)
533 client->router = from;
542 /* All are changed */
547 SILC_LOG_DEBUG(("Client changed to %s",
548 silc_id_render(client->router->id, SILC_ID_SERVER)));
550 if (!silc_idcache_list_next(list, &id_cache))
554 silc_idcache_list_free(list);
558 if (silc_idcache_get_all(server->local_list->clients, &list)) {
559 if (silc_idcache_list_first(list, &id_cache)) {
561 client = (SilcClientEntry)id_cache->context;
563 /* If entry is disabled skip it. If entry is local to us, do not
564 switch it to anyone else, it is ours so skip it. */
565 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
566 SILC_IS_LOCAL(client)) {
567 if (!silc_idcache_list_next(list, &id_cache))
573 SILC_LOG_DEBUG(("Client %s",
574 silc_id_render(client->id, SILC_ID_CLIENT)));
576 SILC_LOG_DEBUG(("Client->router %s",
577 silc_id_render(client->router->id, SILC_ID_SERVER)));
580 if (client->router == from) {
581 if (resolve_real_server) {
583 silc_server_update_clients_by_real_server(server, from, to,
587 client->router = from;
593 /* All are changed */
598 SILC_LOG_DEBUG(("Client changed to %s",
599 silc_id_render(client->router->id, SILC_ID_SERVER)));
601 if (!silc_idcache_list_next(list, &id_cache))
605 silc_idcache_list_free(list);
609 /* Updates servers that are from `from' to be originated from `to'. This
610 will also update the server's connection to `to's connection. */
612 void silc_server_update_servers_by_server(SilcServer server,
613 SilcServerEntry from,
616 SilcIDCacheList list = NULL;
617 SilcIDCacheEntry id_cache = NULL;
618 SilcServerEntry server_entry = NULL;
620 SILC_LOG_DEBUG(("Updating servers"));
622 if (silc_idcache_get_all(server->local_list->servers, &list)) {
623 if (silc_idcache_list_first(list, &id_cache)) {
625 server_entry = (SilcServerEntry)id_cache->context;
627 /* If entry is local to us, do not switch it to any anyone else,
629 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
630 server_entry == from) {
631 if (!silc_idcache_list_next(list, &id_cache))
637 /* If we are standalone router, any server that is not directly
638 connected to cannot exist anymore. If we are not standalone
639 we update it correctly. */
640 if (server->server_type == SILC_ROUTER && server->standalone) {
641 silc_server_backup_del(server, server_entry);
642 silc_server_backup_replaced_del(server, server_entry);
643 silc_idlist_del_data(server_entry);
644 silc_idlist_del_server(server->local_list, server_entry);
645 server->stat.servers--;
646 server->stat.cell_servers--;
648 /* XXX if we are not standalone, do a check from local config
649 whether this server is in our cell, but not connected to
650 us (in which case we must remove it). */
652 if (server_entry->router == from) {
653 SILC_LOG_DEBUG(("Updating server (local) %s",
654 server_entry->server_name ?
655 server_entry->server_name : ""));
656 server_entry->router = to;
657 server_entry->connection = to->connection;
661 if (!silc_idcache_list_next(list, &id_cache))
665 silc_idcache_list_free(list);
668 if (silc_idcache_get_all(server->global_list->servers, &list)) {
669 if (silc_idcache_list_first(list, &id_cache)) {
671 server_entry = (SilcServerEntry)id_cache->context;
673 /* If entry is local to us, do not switch it to anyone else,
675 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
676 server_entry == from) {
677 if (!silc_idcache_list_next(list, &id_cache))
683 /* If we are standalone router, any server that is not directly
684 connected to cannot exist anymore. If we are not standalone
685 we update it correctly. */
686 if (server->server_type == SILC_ROUTER && server->standalone) {
687 silc_server_backup_del(server, server_entry);
688 silc_server_backup_replaced_del(server, server_entry);
689 silc_idlist_del_data(server_entry);
690 silc_idlist_del_server(server->global_list, server_entry);
691 server->stat.servers--;
692 server->stat.cell_servers--;
694 /* XXX if we are not standalone, do a check from local config
695 whether this server is in our cell, but not connected to
696 us (in which case we must remove it). */
698 if (server_entry->router == from) {
699 SILC_LOG_DEBUG(("Updating server (global) %s",
700 server_entry->server_name ?
701 server_entry->server_name : ""));
702 server_entry->router = to;
703 server_entry->connection = to->connection;
707 if (!silc_idcache_list_next(list, &id_cache))
711 silc_idcache_list_free(list);
716 /* Toggles the enabled/disabled status of local server connections. Packets
717 can be sent to the servers when `toggle_enabled' is TRUE and will be
718 dropped if `toggle_enabled' is FALSE, after this function is called. */
720 void silc_server_local_servers_toggle_enabled(SilcServer server,
723 SilcIDCacheList list = NULL;
724 SilcIDCacheEntry id_cache = NULL;
725 SilcServerEntry server_entry = NULL;
727 if (silc_idcache_get_all(server->local_list->servers, &list)) {
728 if (silc_idcache_list_first(list, &id_cache)) {
730 server_entry = (SilcServerEntry)id_cache->context;
731 if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry) {
732 if (!silc_idcache_list_next(list, &id_cache))
739 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
741 server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
743 if (!silc_idcache_list_next(list, &id_cache))
747 silc_idcache_list_free(list);
750 if (silc_idcache_get_all(server->global_list->servers, &list)) {
751 if (silc_idcache_list_first(list, &id_cache)) {
753 server_entry = (SilcServerEntry)id_cache->context;
754 if (!SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry) {
755 if (!silc_idcache_list_next(list, &id_cache))
762 server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
764 server_entry->data.status |= SILC_IDLIST_STATUS_DISABLED;
766 if (!silc_idcache_list_next(list, &id_cache))
770 silc_idcache_list_free(list);
774 /* Removes servers that are originated from the `from'. The server
775 entry is deleted in this function. If `remove_clients' is TRUE then
776 all clients originated from the server are removed too, and server
777 signoff is sent. Note that this does not remove the `from'. This
778 also does not remove locally connected servers. */
780 void silc_server_remove_servers_by_server(SilcServer server,
781 SilcServerEntry from,
784 SilcIDCacheList list = NULL;
785 SilcIDCacheEntry id_cache = NULL;
786 SilcServerEntry server_entry = NULL;
788 SILC_LOG_DEBUG(("Removing servers by %s",
789 from->server_name ? from->server_name : "server"));
791 if (silc_idcache_get_all(server->local_list->servers, &list)) {
792 if (silc_idcache_list_first(list, &id_cache)) {
794 server_entry = (SilcServerEntry)id_cache->context;
795 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
796 server_entry->router != from || server_entry == from) {
797 if (!silc_idcache_list_next(list, &id_cache))
803 /* Remove clients owned by this server */
805 silc_server_remove_clients_by_server(server, from, server_entry,
808 /* Remove the server */
809 silc_idlist_del_server(server->local_list, server_entry);
811 if (!silc_idcache_list_next(list, &id_cache))
815 silc_idcache_list_free(list);
818 if (silc_idcache_get_all(server->global_list->servers, &list)) {
819 if (silc_idcache_list_first(list, &id_cache)) {
821 server_entry = (SilcServerEntry)id_cache->context;
822 if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
823 server_entry->router != from || server_entry == from) {
824 if (!silc_idcache_list_next(list, &id_cache))
830 /* Remove clients owned by this server */
832 silc_server_remove_clients_by_server(server, from, server_entry,
835 /* Remove the server */
836 silc_idlist_del_server(server->global_list, server_entry);
838 if (!silc_idcache_list_next(list, &id_cache))
842 silc_idcache_list_free(list);
846 /* Removes channels that are from `from. */
848 void silc_server_remove_channels_by_server(SilcServer server,
849 SilcServerEntry from)
851 SilcIDCacheList list = NULL;
852 SilcIDCacheEntry id_cache = NULL;
853 SilcChannelEntry channel = NULL;
855 SILC_LOG_DEBUG(("Removing channels by server"));
857 if (silc_idcache_get_all(server->global_list->channels, &list)) {
858 if (silc_idcache_list_first(list, &id_cache)) {
860 channel = (SilcChannelEntry)id_cache->context;
861 if (channel->router == from)
862 silc_idlist_del_channel(server->global_list, channel);
863 if (!silc_idcache_list_next(list, &id_cache))
867 silc_idcache_list_free(list);
871 /* Updates channels that are from `from' to be originated from `to'. */
873 void silc_server_update_channels_by_server(SilcServer server,
874 SilcServerEntry from,
877 SilcIDCacheList list = NULL;
878 SilcIDCacheEntry id_cache = NULL;
879 SilcChannelEntry channel = NULL;
881 SILC_LOG_DEBUG(("Updating channels by server"));
883 if (silc_idcache_get_all(server->global_list->channels, &list)) {
884 if (silc_idcache_list_first(list, &id_cache)) {
886 channel = (SilcChannelEntry)id_cache->context;
887 if (channel->router == from)
888 channel->router = to;
889 if (!silc_idcache_list_next(list, &id_cache))
893 silc_idcache_list_free(list);
897 /* Checks whether given channel has global users. If it does this returns
898 TRUE and FALSE if there is only locally connected clients on the channel. */
900 bool silc_server_channel_has_global(SilcChannelEntry channel)
902 SilcChannelClientEntry chl;
903 SilcHashTableList htl;
905 silc_hash_table_list(channel->user_list, &htl);
906 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
907 if (chl->client->router) {
908 silc_hash_table_list_reset(&htl);
912 silc_hash_table_list_reset(&htl);
917 /* Checks whether given channel has locally connected users. If it does this
918 returns TRUE and FALSE if there is not one locally connected client. */
920 bool silc_server_channel_has_local(SilcChannelEntry channel)
922 SilcChannelClientEntry chl;
923 SilcHashTableList htl;
925 silc_hash_table_list(channel->user_list, &htl);
926 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
927 if (SILC_IS_LOCAL(chl->client)) {
928 silc_hash_table_list_reset(&htl);
932 silc_hash_table_list_reset(&htl);
937 /* This function removes the channel and all users on the channel, unless
938 the channel is permanent. In this case the channel is disabled but all
939 users are removed from the channel. Returns TRUE if the channel is
940 destroyed totally, and FALSE if it is permanent and remains. */
942 bool silc_server_channel_delete(SilcServer server,
943 SilcChannelEntry channel)
945 SilcChannelClientEntry chl;
946 SilcHashTableList htl;
947 bool delchan = !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH);
950 /* Update statistics */
951 if (server->server_type == SILC_ROUTER)
952 server->stat.chanclients -= channel->user_count;
954 /* Totally delete the channel and all users on the channel. The
955 users are deleted automatically in silc_idlist_del_channel. */
956 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
957 if (silc_idlist_del_channel(server->local_list, channel)) {
958 server->stat.my_channels--;
959 if (server->server_type == SILC_ROUTER) {
960 server->stat.channels--;
961 server->stat.cell_channels--;
964 if (silc_idlist_del_channel(server->global_list, channel))
965 if (server->server_type == SILC_ROUTER)
966 server->stat.channels--;
972 /* Channel is permanent, do not remove it, remove only users */
973 channel->disabled = TRUE;
974 silc_hash_table_list(channel->user_list, &htl);
975 while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
976 silc_hash_table_del(chl->client->channels, channel);
977 silc_hash_table_del(channel->user_list, chl->client);
978 channel->user_count--;
980 /* Update statistics */
981 if (SILC_IS_LOCAL(chl->client))
982 server->stat.my_chanclients--;
983 if (server->server_type == SILC_ROUTER) {
984 server->stat.cell_chanclients--;
985 server->stat.chanclients--;
990 silc_hash_table_list_reset(&htl);
992 SILC_LOG_DEBUG(("Channel %s remains", channel->channel_name));
997 /* Returns TRUE if the given client is on the channel. FALSE if not.
998 This works because we assure that the user list on the channel is
999 always in up to date thus we can only check the channel list from
1000 `client' which is faster than checking the user list from `channel'. */
1002 bool silc_server_client_on_channel(SilcClientEntry client,
1003 SilcChannelEntry channel,
1004 SilcChannelClientEntry *chl)
1006 if (!client || !channel)
1009 return silc_hash_table_find(client->channels, channel, NULL,
1013 /* Checks string for bad characters and returns TRUE if they are found. */
1015 bool silc_server_name_bad_chars(const char *name, SilcUInt32 name_len)
1019 for (i = 0; i < name_len; i++) {
1020 if (!isascii(name[i]))
1022 if (name[i] <= 32) return TRUE;
1023 if (name[i] == ' ') return TRUE;
1024 if (name[i] == '*') return TRUE;
1025 if (name[i] == '?') return TRUE;
1026 if (name[i] == ',') return TRUE;
1032 /* Modifies the `name' if it includes bad characters and returns new
1033 allocated name that does not include bad characters. */
1035 char *silc_server_name_modify_bad(const char *name, SilcUInt32 name_len)
1038 char *newname = strdup(name);
1040 for (i = 0; i < name_len; i++) {
1041 if (!isascii(newname[i])) newname[i] = '_';
1042 if (newname[i] <= 32) newname[i] = '_';
1043 if (newname[i] == ' ') newname[i] = '_';
1044 if (newname[i] == '*') newname[i] = '_';
1045 if (newname[i] == '?') newname[i] = '_';
1046 if (newname[i] == ',') newname[i] = '_';
1052 /* Find number of sockets by IP address indicated by `ip'. Returns 0 if
1053 socket connections with the IP address does not exist. */
1055 SilcUInt32 silc_server_num_sockets_by_ip(SilcServer server, const char *ip,
1056 SilcSocketType type)
1060 for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
1061 if (server->sockets[i] && !SILC_IS_LISTENER(server->sockets[i]) &&
1062 !strcmp(server->sockets[i]->ip, ip) &&
1063 server->sockets[i]->type == type)
1070 /* Find number of sockets by IP address indicated by remote host, indicatd
1071 by `ip' or `hostname', `port', and `type'. Returns 0 if socket connections
1072 does not exist. If `ip' is provided then `hostname' is ignored. */
1074 SilcUInt32 silc_server_num_sockets_by_remote(SilcServer server,
1076 const char *hostname,
1078 SilcSocketType type)
1082 if (!ip && !hostname)
1085 for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
1086 if (server->sockets[i] && !SILC_IS_LISTENER(server->sockets[i]) &&
1087 ((ip && !strcmp(server->sockets[i]->ip, ip)) ||
1088 (hostname && !strcmp(server->sockets[i]->hostname, hostname))) &&
1089 server->sockets[i]->port == port &&
1090 server->sockets[i]->type == type)
1097 /* Finds locally cached public key by the public key received in the SKE.
1098 If we have it locally cached then we trust it and will use it in the
1099 authentication protocol. Returns the locally cached public key or NULL
1100 if we do not find the public key. */
1102 SilcPublicKey silc_server_find_public_key(SilcServer server,
1103 SilcHashTable local_public_keys,
1104 SilcPublicKey remote_public_key)
1106 SilcPublicKey cached_key;
1108 SILC_LOG_DEBUG(("Find remote public key (%d keys in local cache)",
1109 silc_hash_table_count(local_public_keys)));
1111 if (!silc_hash_table_find_ext(local_public_keys, remote_public_key,
1112 (void **)&cached_key, NULL,
1113 silc_hash_public_key, NULL,
1114 silc_hash_public_key_compare, NULL)) {
1115 SILC_LOG_ERROR(("Public key not found"));
1119 SILC_LOG_DEBUG(("Found public key"));
1124 /* This returns the first public key from the table of public keys. This
1125 is used only in cases where single public key exists in the table and
1126 we want to get a pointer to it. For public key tables that has multiple
1127 keys in it the silc_server_find_public_key must be used. */
1129 SilcPublicKey silc_server_get_public_key(SilcServer server,
1130 SilcHashTable local_public_keys)
1132 SilcPublicKey cached_key;
1133 SilcHashTableList htl;
1135 SILC_LOG_DEBUG(("Start"));
1137 assert(silc_hash_table_count(local_public_keys) < 2);
1139 silc_hash_table_list(local_public_keys, &htl);
1140 if (!silc_hash_table_get(&htl, NULL, (void **)&cached_key))
1142 silc_hash_table_list_reset(&htl);
1147 /* Check whether the connection `sock' is allowed to connect to us. This
1148 checks for example whether there is too much connections for this host,
1149 and required version for the host etc. */
1151 bool silc_server_connection_allowed(SilcServer server,
1152 SilcSocketConnection sock,
1153 SilcSocketType type,
1154 SilcServerConfigConnParams *global,
1155 SilcServerConfigConnParams *params,
1158 SilcUInt32 conn_number = (type == SILC_SOCKET_TYPE_CLIENT ?
1159 server->stat.my_clients :
1160 type == SILC_SOCKET_TYPE_SERVER ?
1161 server->stat.my_servers :
1162 server->stat.my_routers);
1163 SilcUInt32 num_sockets, max_hosts, max_per_host;
1164 SilcUInt32 r_protocol_version, l_protocol_version;
1165 SilcUInt32 r_software_version, l_software_version;
1166 char *r_vendor_version = NULL, *l_vendor_version;
1168 SILC_LOG_DEBUG(("Checking whether connection is allowed"));
1172 l_protocol_version =
1173 silc_version_to_num(params && params->version_protocol ?
1174 params->version_protocol :
1175 global->version_protocol);
1176 l_software_version =
1177 silc_version_to_num(params && params->version_software ?
1178 params->version_software :
1179 global->version_software);
1180 l_vendor_version = (params && params->version_software_vendor ?
1181 params->version_software_vendor :
1182 global->version_software_vendor);
1184 if (ske && silc_ske_parse_version(ske, &r_protocol_version, NULL,
1185 &r_software_version, NULL,
1186 &r_vendor_version)) {
1187 sock->version = r_protocol_version;
1189 /* Match protocol version */
1190 if (l_protocol_version && r_protocol_version &&
1191 r_protocol_version < l_protocol_version) {
1192 SILC_LOG_INFO(("Connection %s (%s) is too old version",
1193 sock->hostname, sock->ip));
1194 silc_server_disconnect_remote(server, sock,
1195 SILC_STATUS_ERR_BAD_VERSION,
1196 "You support too old protocol version");
1200 /* Math software version */
1201 if (l_software_version && r_software_version &&
1202 r_software_version < l_software_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 software version");
1211 /* Regex match vendor version */
1212 if (l_vendor_version && r_vendor_version &&
1213 !silc_string_match(l_vendor_version, r_vendor_version)) {
1214 SILC_LOG_INFO(("Connection %s (%s) is unsupported version",
1215 sock->hostname, sock->ip));
1216 silc_server_disconnect_remote(server, sock,
1217 SILC_STATUS_ERR_BAD_VERSION,
1218 "Your software is not supported");
1222 silc_free(r_vendor_version);
1224 /* Check for maximum connections limit */
1226 num_sockets = silc_server_num_sockets_by_ip(server, sock->ip, type);
1227 max_hosts = (params ? params->connections_max : global->connections_max);
1228 max_per_host = (params ? params->connections_max_per_host :
1229 global->connections_max_per_host);
1231 if (max_hosts && conn_number >= max_hosts) {
1232 SILC_LOG_INFO(("Server is full, closing %s (%s) connection",
1233 sock->hostname, sock->ip));
1234 silc_server_disconnect_remote(server, sock,
1235 SILC_STATUS_ERR_RESOURCE_LIMIT,
1236 "Server is full, try again later");
1240 if (num_sockets >= max_per_host) {
1241 SILC_LOG_INFO(("Too many connections from %s (%s), closing connection",
1242 sock->hostname, sock->ip));
1243 silc_server_disconnect_remote(server, sock,
1244 SILC_STATUS_ERR_RESOURCE_LIMIT,
1245 "Too many connections from your host");
1252 /* Checks that client has rights to add or remove channel modes. If any
1253 of the checks fails FALSE is returned. */
1255 bool silc_server_check_cmode_rights(SilcServer server,
1256 SilcChannelEntry channel,
1257 SilcChannelClientEntry client,
1260 bool is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1261 bool is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1263 /* Check whether has rights to change anything */
1264 if (!is_op && !is_fo)
1267 /* Check whether has rights to change everything */
1271 /* Founder implies operator */
1275 /* We know that client is channel operator, check that they are not
1276 changing anything that requires channel founder rights. Rest of the
1277 modes are available automatically for channel operator. */
1279 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1280 if (is_op && !is_fo)
1283 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1284 if (is_op && !is_fo)
1289 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1290 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
1291 if (is_op && !is_fo)
1295 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1296 if (is_op && !is_fo)
1301 if (mode & SILC_CHANNEL_MODE_CIPHER) {
1302 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
1303 if (is_op && !is_fo)
1307 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1308 if (is_op && !is_fo)
1313 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1314 if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
1315 if (is_op && !is_fo)
1319 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1320 if (is_op && !is_fo)
1325 if (mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1326 if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS)) {
1327 if (is_op && !is_fo)
1331 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1332 if (is_op && !is_fo)
1337 if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1338 if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS)) {
1339 if (is_op && !is_fo)
1343 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1344 if (is_op && !is_fo)
1352 /* Check that the client has rights to change its user mode. Returns
1353 FALSE if setting some mode is not allowed. */
1355 bool silc_server_check_umode_rights(SilcServer server,
1356 SilcClientEntry client,
1359 bool server_op = FALSE, router_op = FALSE;
1361 if (mode & SILC_UMODE_SERVER_OPERATOR) {
1362 /* Cannot set server operator mode (must use OPER command) */
1363 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR))
1366 /* Remove the server operator rights */
1367 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
1371 if (mode & SILC_UMODE_ROUTER_OPERATOR) {
1372 /* Cannot set router operator mode (must use SILCOPER command) */
1373 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR))
1376 /* Remove the router operator rights */
1377 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
1382 SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR);
1384 SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR);
1389 /* This function is used to send the notify packets and motd to the
1390 incoming client connection. */
1392 void silc_server_send_connect_notifys(SilcServer server,
1393 SilcSocketConnection sock,
1394 SilcClientEntry client)
1396 SilcIDListData idata = (SilcIDListData)client;
1398 SILC_LOG_DEBUG(("Send welcome notifys"));
1400 /* Send some nice info to the client */
1401 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1402 ("Welcome to the SILC Network %s",
1404 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1405 ("Your host is %s, running version %s",
1406 server->server_name, server_version));
1408 if (server->server_type == SILC_ROUTER) {
1409 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1410 ("There are %d clients, %d servers and %d "
1411 "routers in SILC Network",
1412 server->stat.clients, server->stat.servers + 1,
1413 server->stat.routers));
1415 if (server->stat.clients && server->stat.servers + 1)
1416 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1417 ("There are %d clients, %d servers and %d "
1418 "routers in SILC Network",
1419 server->stat.clients, server->stat.servers + 1,
1420 (server->standalone ? 0 :
1421 !server->stat.routers ? 1 :
1422 server->stat.routers)));
1425 if (server->stat.cell_clients && server->stat.cell_servers + 1)
1426 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1427 ("There are %d clients on %d server in our cell",
1428 server->stat.cell_clients,
1429 server->stat.cell_servers + 1));
1430 if (server->server_type == SILC_ROUTER) {
1431 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1432 ("I have %d clients, %d channels, %d servers and "
1434 server->stat.my_clients,
1435 server->stat.my_channels,
1436 server->stat.my_servers,
1437 server->stat.my_routers));
1439 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1440 ("I have %d clients and %d channels formed",
1441 server->stat.my_clients,
1442 server->stat.my_channels));
1445 if (server->stat.server_ops || server->stat.router_ops)
1446 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1447 ("There are %d server operators and %d router "
1449 server->stat.server_ops,
1450 server->stat.router_ops));
1451 if (server->stat.my_router_ops + server->stat.my_server_ops)
1452 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1453 ("I have %d operators online",
1454 server->stat.my_router_ops +
1455 server->stat.my_server_ops));
1457 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1458 ("Your connection is secured with %s cipher, "
1459 "key length %d bits",
1460 silc_cipher_get_name(idata->send_key),
1461 silc_cipher_get_key_len(idata->send_key)));
1462 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1463 ("Your current nickname is %s",
1467 silc_server_send_motd(server, sock);
1470 /* Kill the client indicated by `remote_client' sending KILLED notify
1471 to the client, to all channels client has joined and to primary
1472 router if needed. The killed client is also removed from all channels. */
1474 void silc_server_kill_client(SilcServer server,
1475 SilcClientEntry remote_client,
1476 const char *comment,
1478 SilcIdType killer_id_type)
1480 SilcBuffer killed, killer;
1482 SILC_LOG_DEBUG(("Killing client %s",
1483 silc_id_render(remote_client->id, SILC_ID_CLIENT)));
1485 /* Send the KILL notify packets. First send it to the channel, then
1486 to our primary router and then directly to the client who is being
1487 killed right now. */
1489 killed = silc_id_payload_encode(remote_client->id, SILC_ID_CLIENT);
1490 killer = silc_id_payload_encode(killer_id, killer_id_type);
1492 /* Send KILLED notify to the channels. It is not sent to the client
1493 as it will be sent differently destined directly to the client and not
1495 silc_server_send_notify_on_channels(server, remote_client,
1496 remote_client, SILC_NOTIFY_TYPE_KILLED,
1497 3, killed->data, killed->len,
1498 comment, comment ? strlen(comment) : 0,
1499 killer->data, killer->len);
1501 /* Send KILLED notify to primary route */
1502 silc_server_send_notify_killed(server, SILC_PRIMARY_ROUTE(server),
1503 SILC_BROADCAST(server), remote_client->id,
1504 comment, killer_id, killer_id_type);
1506 /* Send KILLED notify to the client directly */
1507 if (remote_client->connection || remote_client->router)
1508 silc_server_send_notify_killed(server, remote_client->connection ?
1509 remote_client->connection :
1510 remote_client->router->connection, FALSE,
1511 remote_client->id, comment,
1512 killer_id, killer_id_type);
1514 /* Remove the client from all channels. This generates new keys to the
1515 channels as well. */
1516 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
1519 /* Remove the client entry, If it is locally connected then we will also
1520 disconnect the client here */
1521 if (remote_client->connection) {
1522 /* Remove locally conneted client */
1523 SilcSocketConnection sock = remote_client->connection;
1524 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
1525 silc_server_close_connection(server, sock);
1527 /* Update statistics */
1528 server->stat.clients--;
1529 if (server->stat.cell_clients)
1530 server->stat.cell_clients--;
1531 SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
1532 SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
1534 if (SILC_IS_LOCAL(remote_client)) {
1535 server->stat.my_clients--;
1536 silc_schedule_task_del_by_context(server->schedule, remote_client);
1537 silc_idlist_del_data(remote_client);
1540 /* Remove remote client */
1541 silc_idlist_del_data(remote_client);
1542 if (!silc_idlist_del_client(server->global_list, remote_client)) {
1543 /* Remove this client from watcher list if it is */
1544 silc_server_del_from_watcher_list(server, remote_client);
1545 silc_idlist_del_client(server->local_list, remote_client);
1549 silc_buffer_free(killer);
1550 silc_buffer_free(killed);
1555 SilcClientEntry client;
1556 SilcNotifyType notify;
1557 const char *new_nick;
1558 } WatcherNotifyContext;
1561 silc_server_check_watcher_list_foreach(void *key, void *context,
1564 WatcherNotifyContext *notify = user_context;
1565 SilcClientEntry entry = context;
1566 SilcSocketConnection sock;
1571 if (entry == notify->client)
1574 sock = silc_server_get_client_route(notify->server, NULL, 0, entry->id,
1577 SILC_LOG_DEBUG(("Sending WATCH notify to %s",
1578 silc_id_render(entry->id, SILC_ID_CLIENT)));
1580 /* Send the WATCH notify */
1581 silc_server_send_notify_watch(notify->server, sock, entry,
1583 notify->new_nick ? notify->new_nick :
1584 (const char *)notify->client->nickname,
1589 /* This function checks whether the `client' nickname is being watched
1590 by someone, and notifies the watcher of the notify change of notify
1591 type indicated by `notify'. */
1593 bool silc_server_check_watcher_list(SilcServer server,
1594 SilcClientEntry client,
1595 const char *new_nick,
1596 SilcNotifyType notify)
1598 unsigned char hash[16];
1599 WatcherNotifyContext n;
1601 SILC_LOG_DEBUG(("Checking watcher list %s",
1602 client->nickname ? client->nickname : (unsigned char *)""));
1604 /* If the watching is rejected by the client do nothing */
1605 if (client->mode & SILC_UMODE_REJECT_WATCHING)
1608 /* Make hash from the nick, or take it from Client ID */
1609 if (client->nickname) {
1611 memset(nick, 0, sizeof(nick));
1612 silc_to_lower(client->nickname, nick, sizeof(nick) - 1);
1613 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
1615 memset(hash, 0, sizeof(hash));
1616 memcpy(hash, client->id->hash, sizeof(client->id->hash));
1621 n.new_nick = new_nick;
1624 /* Send notify to all watchers */
1625 silc_hash_table_find_foreach(server->watcher_list, hash,
1626 silc_server_check_watcher_list_foreach, &n);
1631 /* Remove the `client' from watcher list. After calling this the `client'
1632 is not watching any nicknames. */
1634 bool silc_server_del_from_watcher_list(SilcServer server,
1635 SilcClientEntry client)
1637 SilcHashTableList htl;
1639 SilcClientEntry entry;
1642 silc_hash_table_list(server->watcher_list, &htl);
1643 while (silc_hash_table_get(&htl, &key, (void **)&entry)) {
1644 if (entry == client) {
1645 silc_hash_table_del_by_context(server->watcher_list, key, client);
1648 SILC_LOG_DEBUG(("Removing %s from WATCH list",
1649 silc_id_render(client->id, SILC_ID_CLIENT)));
1651 /* Now check whether there still exists entries with this key, if not
1652 then free the key to not leak memory. */
1653 if (!silc_hash_table_find(server->watcher_list, key, NULL, NULL))
1659 silc_hash_table_list_reset(&htl);
1664 /* Force the client indicated by `chl' to change the channel user mode
1665 on channel indicated by `channel' to `forced_mode'. */
1667 bool silc_server_force_cumode_change(SilcServer server,
1668 SilcSocketConnection sock,
1669 SilcChannelEntry channel,
1670 SilcChannelClientEntry chl,
1671 SilcUInt32 forced_mode)
1673 SilcBuffer idp1, idp2;
1674 unsigned char cumode[4];
1676 SILC_LOG_DEBUG(("Enforcing sender to change mode"));
1679 silc_server_send_notify_cumode(server, sock, FALSE, channel, forced_mode,
1680 server->id, SILC_ID_SERVER,
1681 chl->client->id, NULL);
1683 idp1 = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1684 idp2 = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
1685 SILC_PUT32_MSB(forced_mode, cumode);
1686 silc_server_send_notify_to_channel(server, sock, channel, FALSE,
1687 SILC_NOTIFY_TYPE_CUMODE_CHANGE,
1688 3, idp1->data, idp1->len,
1689 cumode, sizeof(cumode),
1690 idp2->data, idp2->len);
1691 silc_buffer_free(idp1);
1692 silc_buffer_free(idp2);
1697 /* Find active socket connection by the IP address and port indicated by
1698 `ip' and `port', and socket connection type of `type'. */
1700 SilcSocketConnection
1701 silc_server_find_socket_by_host(SilcServer server,
1702 SilcSocketType type,
1703 const char *ip, SilcUInt16 port)
1707 for (i = 0; i < server->config->param.connections_max; i++) {
1708 if (!server->sockets[i])
1710 if (!strcmp(server->sockets[i]->ip, ip) &&
1711 (!port || server->sockets[i]->port == port) &&
1712 server->sockets[i]->type == type)
1713 return server->sockets[i];
1719 /* This function can be used to match the invite and ban lists. */
1721 bool silc_server_inviteban_match(SilcServer server, SilcHashTable list,
1722 SilcUInt8 type, void *check)
1724 unsigned char *tmp = NULL;
1725 SilcUInt32 len = 0, t;
1726 SilcHashTableList htl;
1730 if (type < 1 || type > 3 || !check)
1734 tmp = strdup((char *)check);
1739 tmp = silc_pkcs_public_key_encode(check, &len);
1744 tmp = silc_id_id2str(check, SILC_ID_CLIENT);
1747 len = silc_id_get_len(check, SILC_ID_CLIENT);
1750 /* Compare the list */
1751 silc_hash_table_list(list, &htl);
1752 while (silc_hash_table_get(&htl, (void **)&t, (void **)&entry)) {
1755 if (silc_string_match((char *)entry, tmp)) {
1759 } else if (!memcmp(entry->data, tmp, len)) {
1765 silc_hash_table_list_reset(&htl);
1771 /* Process invite or ban information */
1773 void silc_server_inviteban_process(SilcServer server, SilcHashTable list,
1774 SilcUInt8 action, SilcArgumentPayload args)
1777 SilcUInt32 type, len;
1779 SilcHashTableList htl;
1781 SILC_LOG_DEBUG(("Processing invite/ban for %s action",
1782 action == 0x00 ? "ADD" : "DEL"));
1784 /* Add the information to invite list */
1785 if (action == 0x00) {
1786 /* Traverse all arguments and add to the hash table according to
1788 tmp = silc_argument_get_first_arg(args, &type, &len);
1791 /* Invite string. Get the old invite string from hash table
1792 and append this at the end of the existing one. */
1793 char *string = NULL;
1794 silc_hash_table_find(list, (void *)1,
1795 NULL, (void **)&string);
1796 silc_hash_table_del(list, (void *)1);
1798 string = silc_calloc(len + 2, sizeof(*string));
1800 string = silc_realloc(string, sizeof(*string) *
1801 (strlen(string) + len + 2));
1802 memset(string + strlen(string), 0, len + 2);
1803 if (tmp[len - 1] == ',')
1804 tmp[len - 1] = '\0';
1805 strncat(string, tmp, len);
1806 strncat(string, ",", 1);
1808 /* Add new invite string to invite list */
1809 silc_hash_table_add(list, (void *)1, string);
1811 } else if (type == 2) {
1812 /* Public key. Check first if the public key is already on the
1813 list and ignore it if it is, otherwise, add it to hash table. */
1815 /* Check if the public key is in the list already */
1816 silc_hash_table_list(list, &htl);
1817 while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
1818 if (type == 2 && !memcmp(tmp2->data, tmp, len)) {
1823 silc_hash_table_list_reset(&htl);
1825 /* Add new public key to invite list */
1827 tmp2 = silc_buffer_alloc_size(len);
1828 silc_buffer_put(tmp2, tmp, len);
1829 silc_hash_table_add(list, (void *)2, tmp2);
1832 } else if (type == 3) {
1835 /* Check if the ID is in the list already */
1836 silc_hash_table_list(list, &htl);
1837 while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
1838 if (type == 3 && !memcmp(tmp2->data, tmp, len)) {
1843 silc_hash_table_list_reset(&htl);
1845 /* Add new Client ID to invite list */
1847 tmp2 = silc_buffer_alloc_size(len);
1848 silc_buffer_put(tmp2, tmp, len);
1849 silc_hash_table_add(list, (void *)3, tmp2);
1853 tmp = silc_argument_get_next_arg(args, &type, &len);
1857 /* Delete information to invite list */
1858 if (action == 0x01 && list) {
1859 /* Now delete the arguments from invite list */
1860 tmp = silc_argument_get_first_arg(args, &type, &len);
1863 /* Invite string. Get the old string from hash table and delete
1864 the requested string. */
1865 char *string = NULL, *start, *end, *n;
1867 if (silc_hash_table_find(list, (void *)1, NULL, (void **)&string)) {
1868 silc_hash_table_del(list, (void *)1);
1870 if (!strncmp(string, tmp, strlen(string) - 1)) {
1874 start = strstr(string, tmp);
1875 if (start && strlen(start) >= len) {
1877 n = silc_calloc(strlen(string) - len, sizeof(*n));
1878 strncat(n, string, start - string);
1879 strncat(n, end + 1, ((string + strlen(string)) - end) - 1);
1885 /* Add new invite string to invite list */
1887 silc_hash_table_add(list, (void *)1, string);
1890 } else if (type == 2) {
1893 /* Delete from the invite list */
1894 silc_hash_table_list(list, &htl);
1895 while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
1896 if (type == 2 && !memcmp(tmp2->data, tmp, len)) {
1897 silc_hash_table_del_by_context(list, (void *)2, tmp2);
1898 silc_buffer_free(tmp2);
1902 silc_hash_table_list_reset(&htl);
1904 } else if (type == 3) {
1907 /* Delete from the invite list */
1908 silc_hash_table_list(list, &htl);
1909 while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
1910 if (type == 2 && !memcmp(tmp2->data, tmp, len)) {
1911 silc_hash_table_del_by_context(list, (void *)2, tmp2);
1912 silc_buffer_free(tmp2);
1916 silc_hash_table_list_reset(&htl);
1919 tmp = silc_argument_get_next_arg(args, &type, &len);