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. */
31 static void silc_server_remove_clients_channels(SilcServer server,
32 SilcSocketConnection sock,
33 SilcClientEntry client,
34 SilcHashTable channels)
36 SilcChannelEntry channel;
37 SilcChannelClientEntry chl;
38 SilcHashTableList htl;
41 SILC_LOG_DEBUG(("Start"));
43 if (!client || !client->id)
46 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
48 /* Remove the client from all channels. The client is removed from
49 the channels' user list. */
50 silc_hash_table_list(client->channels, &htl);
51 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
52 channel = chl->channel;
54 /* Remove channel if this is last client leaving the channel, unless
55 the channel is permanent. */
56 if (server->server_type == SILC_ROUTER &&
57 silc_hash_table_count(channel->user_list) < 2) {
58 if (silc_hash_table_find(channels, channel, NULL, NULL))
59 silc_hash_table_del(channels, channel);
60 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
61 silc_server_channel_delete(server, channel);
65 silc_hash_table_del(client->channels, channel);
66 silc_hash_table_del(channel->user_list, chl->client);
67 channel->user_count--;
69 /* If there is no global users on the channel anymore mark the channel
70 as local channel. Do not check if the removed client is local client. */
71 if (server->server_type != SILC_ROUTER && channel->global_users &&
72 chl->client->router && !silc_server_channel_has_global(channel))
73 channel->global_users = FALSE;
76 server->stat.my_chanclients--;
78 /* If there is not at least one local user on the channel then we don't
79 need the channel entry anymore, we can remove it safely, unless the
80 channel is permanent channel */
81 if (server->server_type != SILC_ROUTER &&
82 !silc_server_channel_has_local(channel)) {
83 if (silc_hash_table_find(channels, channel, NULL, NULL))
84 silc_hash_table_del(channels, channel);
85 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
86 silc_server_channel_delete(server, channel);
90 /* Add the channel to the the channels list to regenerate the
92 if (!silc_hash_table_find(channels, channel, NULL, NULL))
93 silc_hash_table_add(channels, channel, channel);
95 silc_hash_table_list_reset(&htl);
96 silc_buffer_free(clidp);
99 /* This function is used to remove all client entries by the server `entry'.
100 This is called when the connection is lost to the server. In this case
101 we must invalidate all the client entries owned by the server `entry'.
102 If the `server_signoff' is TRUE then the SERVER_SIGNOFF notify is
103 distributed to our local clients. */
105 bool silc_server_remove_clients_by_server(SilcServer server,
106 SilcServerEntry entry,
109 SilcIDCacheList list = NULL;
110 SilcIDCacheEntry id_cache = NULL;
111 SilcClientEntry client = NULL;
113 SilcClientEntry *clients = NULL;
114 SilcUInt32 clients_c = 0;
115 unsigned char **argv = NULL;
116 SilcUInt32 *argv_lens = NULL, *argv_types = NULL, argc = 0;
117 SilcHashTableList htl;
118 SilcChannelEntry channel;
119 SilcHashTable channels;
122 SILC_LOG_DEBUG(("Start"));
124 /* Allocate the hash table that holds the channels that require
125 channel key re-generation after we've removed this server's clients
126 from the channels. */
127 channels = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL,
130 if (server_signoff) {
131 idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
132 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
133 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) * (argc + 1));
134 argv_types = silc_realloc(argv_types, sizeof(*argv_types) * (argc + 1));
135 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
136 memcpy(argv[argc], idp->data, idp->len);
137 argv_lens[argc] = idp->len;
138 argv_types[argc] = argc + 1;
140 silc_buffer_free(idp);
143 if (silc_idcache_get_all(server->local_list->clients, &list)) {
145 if (silc_idcache_list_first(list, &id_cache)) {
147 client = (SilcClientEntry)id_cache->context;
148 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
149 if (!silc_idcache_list_next(list, &id_cache))
155 if (client->router != entry) {
156 if (server_signoff) {
157 clients = silc_realloc(clients,
158 sizeof(*clients) * (clients_c + 1));
159 clients[clients_c] = client;
163 if (!silc_idcache_list_next(list, &id_cache))
169 if (server_signoff) {
170 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
171 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
172 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
174 argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
176 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
177 memcpy(argv[argc], idp->data, idp->len);
178 argv_lens[argc] = idp->len;
179 argv_types[argc] = argc + 1;
181 silc_buffer_free(idp);
184 /* Update statistics */
185 server->stat.clients--;
186 if (server->stat.cell_clients)
187 server->stat.cell_clients--;
188 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
189 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
191 /* Remove the client entry */
192 silc_server_remove_clients_channels(server, NULL, client, channels);
193 if (!server_signoff) {
194 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
195 id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
197 /* Remove this client from watcher list if it is */
198 silc_server_del_from_watcher_list(server, client);
199 silc_idlist_del_client(server->local_list, client);
202 if (!silc_idcache_list_next(list, &id_cache))
206 silc_idcache_list_free(list);
209 if (silc_idcache_get_all(server->global_list->clients, &list)) {
211 if (silc_idcache_list_first(list, &id_cache)) {
213 client = (SilcClientEntry)id_cache->context;
214 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
215 if (!silc_idcache_list_next(list, &id_cache))
221 if (client->router != entry) {
222 if (server_signoff && client->connection) {
223 clients = silc_realloc(clients,
224 sizeof(*clients) * (clients_c + 1));
225 clients[clients_c] = client;
229 if (!silc_idcache_list_next(list, &id_cache))
235 if (server_signoff) {
236 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
237 argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
238 argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
240 argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
242 argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
243 memcpy(argv[argc], idp->data, idp->len);
244 argv_lens[argc] = idp->len;
245 argv_types[argc] = argc + 1;
247 silc_buffer_free(idp);
250 /* Update statistics */
251 server->stat.clients--;
252 if (server->stat.cell_clients)
253 server->stat.cell_clients--;
254 SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
255 SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
257 /* Remove the client entry */
258 silc_server_remove_clients_channels(server, NULL, client, channels);
259 if (!server_signoff) {
260 client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
261 id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
263 silc_idlist_del_client(server->global_list, client);
266 if (!silc_idcache_list_next(list, &id_cache))
270 silc_idcache_list_free(list);
273 /* Send the SERVER_SIGNOFF notify */
274 if (server_signoff) {
275 SilcBuffer args, not;
277 /* Send SERVER_SIGNOFF notify to our primary router */
278 if (!server->standalone && server->router &&
279 server->router != entry) {
280 args = silc_argument_payload_encode(1, argv, argv_lens,
282 silc_server_send_notify_args(server,
283 server->router->connection,
284 server->server_type == SILC_SERVER ?
286 SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
288 silc_buffer_free(args);
291 /* Send to local clients. We also send the list of client ID's that
292 is to be removed for those servers that would like to use that list. */
293 args = silc_argument_payload_encode(argc, argv, argv_lens,
295 not = silc_notify_payload_encode_args(SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
297 silc_server_packet_send_clients(server, clients, clients_c,
298 SILC_PACKET_NOTIFY, 0, FALSE,
299 not->data, not->len, FALSE);
302 silc_buffer_free(args);
303 silc_buffer_free(not);
304 for (i = 0; i < argc; i++)
307 silc_free(argv_lens);
308 silc_free(argv_types);
311 /* We must now re-generate the channel key for all channels that had
312 this server's client(s) on the channel. As they left the channel we
313 must re-generate the channel key. */
314 silc_hash_table_list(channels, &htl);
315 while (silc_hash_table_get(&htl, NULL, (void **)&channel)) {
316 if (!silc_server_create_channel_key(server, channel, 0)) {
317 silc_hash_table_list_reset(&htl);
318 silc_hash_table_free(channels);
322 /* Do not send the channel key if private channel key mode is set */
323 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY)
326 silc_server_send_channel_key(server, NULL, channel,
327 server->server_type == SILC_ROUTER ?
328 FALSE : !server->standalone);
330 silc_hash_table_list_reset(&htl);
331 silc_hash_table_free(channels);
336 static SilcServerEntry
337 silc_server_update_clients_by_real_server(SilcServer server,
338 SilcServerEntry from,
339 SilcClientEntry client,
341 SilcIDCacheEntry client_cache)
343 SilcServerEntry server_entry;
344 SilcIDCacheEntry id_cache = NULL;
345 SilcIDCacheList list;
347 if (!silc_idcache_get_all(server->local_list->servers, &list))
350 if (silc_idcache_list_first(list, &id_cache)) {
352 server_entry = (SilcServerEntry)id_cache->context;
353 if (server_entry != from &&
354 SILC_ID_COMPARE(server_entry->id, client->id,
355 client->id->ip.data_len)) {
356 SILC_LOG_DEBUG(("Found (local) %s",
357 silc_id_render(server_entry->id, SILC_ID_SERVER)));
359 if (!server_entry->data.send_key && server_entry->router) {
360 SILC_LOG_DEBUG(("Server not locally connected, use its router"));
361 /* If the client is not marked as local then move it to local list
362 since the server is local. */
364 SILC_LOG_DEBUG(("Moving client to local list"));
365 silc_idcache_add(server->local_list->clients, client_cache->name,
366 client_cache->id, client_cache->context,
367 client_cache->expire, NULL);
368 silc_idcache_del_by_context(server->global_list->clients, client);
370 server_entry = server_entry->router;
372 /* If the client is not marked as local then move it to local list
373 since the server is local. */
374 if (server_entry->server_type != SILC_BACKUP_ROUTER && !local) {
375 SILC_LOG_DEBUG(("Moving client to local list"));
376 silc_idcache_add(server->local_list->clients, client_cache->name,
377 client_cache->id, client_cache->context,
378 client_cache->expire, NULL);
379 silc_idcache_del_by_context(server->global_list->clients, client);
383 silc_idcache_list_free(list);
387 if (!silc_idcache_list_next(list, &id_cache))
392 silc_idcache_list_free(list);
394 if (!silc_idcache_get_all(server->global_list->servers, &list))
397 if (silc_idcache_list_first(list, &id_cache)) {
399 server_entry = (SilcServerEntry)id_cache->context;
400 if (server_entry != from &&
401 SILC_ID_COMPARE(server_entry->id, client->id,
402 client->id->ip.data_len)) {
403 SILC_LOG_DEBUG(("Found (global) %s",
404 silc_id_render(server_entry->id, SILC_ID_SERVER)));
406 if (!server_entry->data.send_key && server_entry->router) {
407 SILC_LOG_DEBUG(("Server not locally connected, use its router"));
408 /* If the client is marked as local then move it to global list
409 since the server is global. */
411 SILC_LOG_DEBUG(("Moving client to global list"));
412 silc_idcache_add(server->global_list->clients, client_cache->name,
413 client_cache->id, client_cache->context,
414 client_cache->expire, NULL);
415 silc_idcache_del_by_context(server->local_list->clients, client);
417 server_entry = server_entry->router;
419 /* If the client is marked as local then move it to global list
420 since the server is global. */
421 if (server_entry->server_type != SILC_BACKUP_ROUTER && local) {
422 SILC_LOG_DEBUG(("Moving client to global list"));
423 silc_idcache_add(server->global_list->clients, client_cache->name,
424 client_cache->id, client_cache->context,
425 client_cache->expire, NULL);
426 silc_idcache_del_by_context(server->local_list->clients, client);
430 silc_idcache_list_free(list);
434 if (!silc_idcache_list_next(list, &id_cache))
439 silc_idcache_list_free(list);
444 /* Updates the clients that are originated from the `from' to be originated
445 from the `to'. If the `resolve_real_server' is TRUE then this will
446 attempt to figure out which clients really are originated from the
447 `from' and which are originated from a server that we have connection
448 to, when we've acting as backup router. If it is FALSE the `to' will
449 be the new source. This function also removes the clients that are
450 *really* originated from `from' if `remove_from' is TRUE. These are
451 clients that the `from' owns, and not just clients that are behind
454 void silc_server_update_clients_by_server(SilcServer server,
455 SilcServerEntry from,
457 bool resolve_real_server,
460 SilcIDCacheList list = NULL;
461 SilcIDCacheEntry id_cache = NULL;
462 SilcClientEntry client = NULL;
465 SILC_LOG_DEBUG(("Start"));
467 SILC_LOG_DEBUG(("Updating %s", silc_id_render(from->id,
469 SILC_LOG_DEBUG(("to %s", silc_id_render(to->id,
474 if (silc_idcache_get_all(server->global_list->clients, &list)) {
475 if (silc_idcache_list_first(list, &id_cache)) {
477 client = (SilcClientEntry)id_cache->context;
478 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
479 if (!silc_idcache_list_next(list, &id_cache))
485 SILC_LOG_DEBUG(("Client (global) %s",
486 silc_id_render(client->id, SILC_ID_CLIENT)));
488 SILC_LOG_DEBUG(("Client->router (global) %s",
489 silc_id_render(client->router->id, SILC_ID_SERVER)));
491 if (client->router == from) {
492 /* Skip clients that are *really* owned by the `from' */
493 if (remove_from && SILC_ID_COMPARE(from->id, client->id,
494 client->id->ip.data_len)) {
495 SILC_LOG_DEBUG(("Found really owned client, skip it"));
496 if (!silc_idcache_list_next(list, &id_cache))
502 if (resolve_real_server) {
504 silc_server_update_clients_by_real_server(server, from, client,
513 if (!silc_idcache_list_next(list, &id_cache))
517 silc_idcache_list_free(list);
521 if (silc_idcache_get_all(server->local_list->clients, &list)) {
522 if (silc_idcache_list_first(list, &id_cache)) {
524 client = (SilcClientEntry)id_cache->context;
525 if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
526 if (!silc_idcache_list_next(list, &id_cache))
532 SILC_LOG_DEBUG(("Client (local) %s",
533 silc_id_render(client->id, SILC_ID_CLIENT)));
535 SILC_LOG_DEBUG(("Client->router (local) %s",
536 silc_id_render(client->router->id, SILC_ID_SERVER)));
538 if (client->router == from) {
539 /* Skip clients that are *really* owned by the `from' */
540 if (remove_from && SILC_ID_COMPARE(from->id, client->id,
541 client->id->ip.data_len)) {
542 SILC_LOG_DEBUG(("Found really owned client, skip it"));
543 if (!silc_idcache_list_next(list, &id_cache))
549 if (resolve_real_server) {
551 silc_server_update_clients_by_real_server(server, from, client,
554 client->router = from; /* on local list put old from */
560 if (!silc_idcache_list_next(list, &id_cache))
564 silc_idcache_list_free(list);
568 /* Now remove the clients that are still marked as orignated from the
569 `from'. These are the clients that really was owned by the `from' and
570 not just exist behind the `from'. */
571 silc_server_remove_clients_by_server(server, from, TRUE);
574 /* Updates servers that are from `from' to be originated from `to'. This
575 will also update the server's connection to `to's connection. */
577 void silc_server_update_servers_by_server(SilcServer server,
578 SilcServerEntry from,
581 SilcIDCacheList list = NULL;
582 SilcIDCacheEntry id_cache = NULL;
583 SilcServerEntry server_entry = NULL;
585 SILC_LOG_DEBUG(("Start"));
587 if (silc_idcache_get_all(server->local_list->servers, &list)) {
588 if (silc_idcache_list_first(list, &id_cache)) {
590 server_entry = (SilcServerEntry)id_cache->context;
591 if (server_entry->router == from) {
592 server_entry->router = to;
593 server_entry->connection = to->connection;
595 if (!silc_idcache_list_next(list, &id_cache))
599 silc_idcache_list_free(list);
602 if (silc_idcache_get_all(server->global_list->servers, &list)) {
603 if (silc_idcache_list_first(list, &id_cache)) {
605 server_entry = (SilcServerEntry)id_cache->context;
606 if (server_entry->router == from) {
607 server_entry->router = to;
608 server_entry->connection = to->connection;
610 if (!silc_idcache_list_next(list, &id_cache))
614 silc_idcache_list_free(list);
618 /* Removes channels that are from `from. */
620 void silc_server_remove_channels_by_server(SilcServer server,
621 SilcServerEntry from)
623 SilcIDCacheList list = NULL;
624 SilcIDCacheEntry id_cache = NULL;
625 SilcChannelEntry channel = NULL;
627 SILC_LOG_DEBUG(("Removing channels by server"));
629 if (silc_idcache_get_all(server->global_list->channels, &list)) {
630 if (silc_idcache_list_first(list, &id_cache)) {
632 channel = (SilcChannelEntry)id_cache->context;
633 if (channel->router == from)
634 silc_idlist_del_channel(server->global_list, channel);
635 if (!silc_idcache_list_next(list, &id_cache))
639 silc_idcache_list_free(list);
643 /* Updates channels that are from `from' to be originated from `to'. */
645 void silc_server_update_channels_by_server(SilcServer server,
646 SilcServerEntry from,
649 SilcIDCacheList list = NULL;
650 SilcIDCacheEntry id_cache = NULL;
651 SilcChannelEntry channel = NULL;
653 SILC_LOG_DEBUG(("Updating channels by server"));
655 if (silc_idcache_get_all(server->global_list->channels, &list)) {
656 if (silc_idcache_list_first(list, &id_cache)) {
658 channel = (SilcChannelEntry)id_cache->context;
659 if (channel->router == from)
660 channel->router = to;
661 if (!silc_idcache_list_next(list, &id_cache))
665 silc_idcache_list_free(list);
669 /* Checks whether given channel has global users. If it does this returns
670 TRUE and FALSE if there is only locally connected clients on the channel. */
672 bool silc_server_channel_has_global(SilcChannelEntry channel)
674 SilcChannelClientEntry chl;
675 SilcHashTableList htl;
677 silc_hash_table_list(channel->user_list, &htl);
678 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
679 if (chl->client->router) {
680 silc_hash_table_list_reset(&htl);
684 silc_hash_table_list_reset(&htl);
689 /* Checks whether given channel has locally connected users. If it does this
690 returns TRUE and FALSE if there is not one locally connected client. */
692 bool silc_server_channel_has_local(SilcChannelEntry channel)
694 SilcChannelClientEntry chl;
695 SilcHashTableList htl;
697 silc_hash_table_list(channel->user_list, &htl);
698 while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
699 if (!chl->client->router) {
700 silc_hash_table_list_reset(&htl);
704 silc_hash_table_list_reset(&htl);
709 /* This function removes the channel and all users on the channel, unless
710 the channel is permanent. In this case the channel is disabled but all
711 users are removed from the channel. Returns TRUE if the channel is
712 destroyed totally, and FALSE if it is permanent and remains. */
714 bool silc_server_channel_delete(SilcServer server,
715 SilcChannelEntry channel)
717 SilcChannelClientEntry chl;
718 SilcHashTableList htl;
719 bool delchan = !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH);
722 SILC_LOG_DEBUG(("Deleting %s channel", channel->channel_name));
724 /* Totally delete the channel and all users on the channel. The
725 users are deleted automatically in silc_idlist_del_channel. */
726 silc_schedule_task_del_by_context(server->schedule, channel->rekey);
727 if (silc_idlist_del_channel(server->local_list, channel))
728 server->stat.my_channels--;
730 silc_idlist_del_channel(server->global_list, channel);
734 /* Channel is permanent, do not remove it, remove only users */
735 channel->disabled = TRUE;
736 silc_hash_table_list(channel->user_list, &htl);
737 while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
738 silc_hash_table_del(chl->client->channels, channel);
739 silc_hash_table_del(channel->user_list, chl->client);
740 channel->user_count--;
743 silc_hash_table_list_reset(&htl);
745 SILC_LOG_DEBUG(("Channel %s remains", channel->channel_name));
750 /* Returns TRUE if the given client is on the channel. FALSE if not.
751 This works because we assure that the user list on the channel is
752 always in up to date thus we can only check the channel list from
753 `client' which is faster than checking the user list from `channel'. */
755 bool silc_server_client_on_channel(SilcClientEntry client,
756 SilcChannelEntry channel,
757 SilcChannelClientEntry *chl)
759 if (!client || !channel)
762 return silc_hash_table_find(client->channels, channel, NULL,
766 /* Checks string for bad characters and returns TRUE if they are found. */
768 bool silc_server_name_bad_chars(const char *name, SilcUInt32 name_len)
772 for (i = 0; i < name_len; i++) {
773 if (!isascii(name[i]))
775 if (name[i] <= 32) return TRUE;
776 if (name[i] == ' ') return TRUE;
777 if (name[i] == '*') return TRUE;
778 if (name[i] == '?') return TRUE;
779 if (name[i] == ',') return TRUE;
785 /* Modifies the `name' if it includes bad characters and returns new
786 allocated name that does not include bad characters. */
788 char *silc_server_name_modify_bad(const char *name, SilcUInt32 name_len)
791 char *newname = strdup(name);
793 for (i = 0; i < name_len; i++) {
794 if (!isascii(newname[i])) newname[i] = '_';
795 if (newname[i] <= 32) newname[i] = '_';
796 if (newname[i] == ' ') newname[i] = '_';
797 if (newname[i] == '*') newname[i] = '_';
798 if (newname[i] == '?') newname[i] = '_';
799 if (newname[i] == ',') newname[i] = '_';
805 /* Find number of sockets by IP address indicated by `ip'. Returns 0 if
806 socket connections with the IP address does not exist. */
808 SilcUInt32 silc_server_num_sockets_by_ip(SilcServer server, const char *ip,
813 for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
814 if (server->sockets[i] && !strcmp(server->sockets[i]->ip, ip) &&
815 server->sockets[i]->type == type)
822 /* Find number of sockets by IP address indicated by remote host, indicatd
823 by `ip' or `hostname', `port', and `type'. Returns 0 if socket connections
824 does not exist. If `ip' is provided then `hostname' is ignored. */
826 SilcUInt32 silc_server_num_sockets_by_remote(SilcServer server,
828 const char *hostname,
834 if (!ip && !hostname)
837 for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
838 if (server->sockets[i] &&
839 ((ip && !strcmp(server->sockets[i]->ip, ip)) ||
840 (hostname && !strcmp(server->sockets[i]->hostname, hostname))) &&
841 server->sockets[i]->port == port &&
842 server->sockets[i]->type == type)
849 /* Finds locally cached public key by the public key received in the SKE.
850 If we have it locally cached then we trust it and will use it in the
851 authentication protocol. Returns the locally cached public key or NULL
852 if we do not find the public key. */
854 SilcPublicKey silc_server_find_public_key(SilcServer server,
855 SilcHashTable local_public_keys,
856 SilcPublicKey remote_public_key)
858 SilcPublicKey cached_key;
860 SILC_LOG_DEBUG(("Find remote public key (%d keys in local cache)",
861 silc_hash_table_count(local_public_keys)));
863 if (!silc_hash_table_find_ext(local_public_keys, remote_public_key,
864 (void **)&cached_key, NULL,
865 silc_hash_public_key, NULL,
866 silc_hash_public_key_compare, NULL)) {
867 SILC_LOG_ERROR(("Public key not found"));
871 SILC_LOG_DEBUG(("Found public key"));
876 /* This returns the first public key from the table of public keys. This
877 is used only in cases where single public key exists in the table and
878 we want to get a pointer to it. For public key tables that has multiple
879 keys in it the silc_server_find_public_key must be used. */
881 SilcPublicKey silc_server_get_public_key(SilcServer server,
882 SilcHashTable local_public_keys)
884 SilcPublicKey cached_key;
885 SilcHashTableList htl;
887 SILC_LOG_DEBUG(("Start"));
889 assert(silc_hash_table_count(local_public_keys) < 2);
891 silc_hash_table_list(local_public_keys, &htl);
892 if (!silc_hash_table_get(&htl, NULL, (void **)&cached_key))
894 silc_hash_table_list_reset(&htl);
899 /* Check whether the connection `sock' is allowed to connect to us. This
900 checks for example whether there is too much connections for this host,
901 and required version for the host etc. */
903 bool silc_server_connection_allowed(SilcServer server,
904 SilcSocketConnection sock,
906 SilcServerConfigConnParams *global,
907 SilcServerConfigConnParams *params,
910 SilcUInt32 conn_number = (type == SILC_SOCKET_TYPE_CLIENT ?
911 server->stat.my_clients :
912 type == SILC_SOCKET_TYPE_SERVER ?
913 server->stat.my_servers :
914 server->stat.my_routers);
915 SilcUInt32 num_sockets, max_hosts, max_per_host;
916 SilcUInt32 r_protocol_version, l_protocol_version;
917 SilcUInt32 r_software_version, l_software_version;
918 char *r_vendor_version = NULL, *l_vendor_version;
923 silc_version_to_num(params && params->version_protocol ?
924 params->version_protocol :
925 global->version_protocol);
927 silc_version_to_num(params && params->version_software ?
928 params->version_software :
929 global->version_software);
930 l_vendor_version = (params && params->version_software_vendor ?
931 params->version_software_vendor :
932 global->version_software_vendor);
934 if (ske && silc_ske_parse_version(ske, &r_protocol_version, NULL,
935 &r_software_version, NULL,
936 &r_vendor_version)) {
937 sock->version = r_protocol_version;
939 /* Match protocol version */
940 if (l_protocol_version && r_protocol_version &&
941 r_protocol_version < l_protocol_version) {
942 SILC_LOG_INFO(("Connection %s (%s) is too old version",
943 sock->hostname, sock->ip));
944 silc_server_disconnect_remote(server, sock,
945 SILC_STATUS_ERR_BAD_VERSION,
946 "You support too old protocol version");
950 /* Math software version */
951 if (l_software_version && r_software_version &&
952 r_software_version < l_software_version) {
953 SILC_LOG_INFO(("Connection %s (%s) is too old version",
954 sock->hostname, sock->ip));
955 silc_server_disconnect_remote(server, sock,
956 SILC_STATUS_ERR_BAD_VERSION,
957 "You support too old software version");
961 /* Regex match vendor version */
962 if (l_vendor_version && r_vendor_version &&
963 !silc_string_match(l_vendor_version, r_vendor_version)) {
964 SILC_LOG_INFO(("Connection %s (%s) is unsupported version",
965 sock->hostname, sock->ip));
966 silc_server_disconnect_remote(server, sock,
967 SILC_STATUS_ERR_BAD_VERSION,
968 "Your software is not supported");
972 silc_free(r_vendor_version);
974 /* Check for maximum connections limit */
976 num_sockets = silc_server_num_sockets_by_ip(server, sock->ip, type);
977 max_hosts = (params ? params->connections_max : global->connections_max);
978 max_per_host = (params ? params->connections_max_per_host :
979 global->connections_max_per_host);
981 if (max_hosts && conn_number >= max_hosts) {
982 SILC_LOG_INFO(("Server is full, closing %s (%s) connection",
983 sock->hostname, sock->ip));
984 silc_server_disconnect_remote(server, sock,
985 SILC_STATUS_ERR_RESOURCE_LIMIT,
986 "Server is full, try again later");
990 if (num_sockets >= max_per_host) {
991 SILC_LOG_INFO(("Too many connections from %s (%s), closing connection",
992 sock->hostname, sock->ip));
993 silc_server_disconnect_remote(server, sock,
994 SILC_STATUS_ERR_RESOURCE_LIMIT,
995 "Too many connections from your host");
1002 /* Checks that client has rights to add or remove channel modes. If any
1003 of the checks fails FALSE is returned. */
1005 bool silc_server_check_cmode_rights(SilcServer server,
1006 SilcChannelEntry channel,
1007 SilcChannelClientEntry client,
1010 bool is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1011 bool is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1013 /* Check whether has rights to change anything */
1014 if (!is_op && !is_fo)
1017 /* Check whether has rights to change everything */
1021 /* Founder implies operator */
1025 /* We know that client is channel operator, check that they are not
1026 changing anything that requires channel founder rights. Rest of the
1027 modes are available automatically for channel operator. */
1029 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1030 if (is_op && !is_fo)
1033 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1034 if (is_op && !is_fo)
1039 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1040 if (is_op && !is_fo)
1043 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1044 if (is_op && !is_fo)
1049 if (mode & SILC_CHANNEL_MODE_CIPHER) {
1050 if (is_op && !is_fo)
1053 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1054 if (is_op && !is_fo)
1059 if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1060 if (is_op && !is_fo)
1063 if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1064 if (is_op && !is_fo)
1069 if (mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1070 if (is_op && !is_fo)
1073 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1074 if (is_op && !is_fo)
1079 if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1080 if (is_op && !is_fo)
1083 if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1084 if (is_op && !is_fo)
1092 /* Check that the client has rights to change its user mode. Returns
1093 FALSE if setting some mode is not allowed. */
1095 bool silc_server_check_umode_rights(SilcServer server,
1096 SilcClientEntry client,
1099 bool server_op = FALSE, router_op = FALSE;
1101 if (mode & SILC_UMODE_SERVER_OPERATOR) {
1102 /* Cannot set server operator mode (must use OPER command) */
1103 if (!(client->mode & SILC_UMODE_SERVER_OPERATOR))
1106 /* Remove the server operator rights */
1107 if (client->mode & SILC_UMODE_SERVER_OPERATOR)
1111 if (mode & SILC_UMODE_ROUTER_OPERATOR) {
1112 /* Cannot set router operator mode (must use SILCOPER command) */
1113 if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR))
1116 /* Remove the router operator rights */
1117 if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
1122 SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR);
1124 SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR);
1129 /* This function is used to send the notify packets and motd to the
1130 incoming client connection. */
1132 void silc_server_send_connect_notifys(SilcServer server,
1133 SilcSocketConnection sock,
1134 SilcClientEntry client)
1136 SilcIDListData idata = (SilcIDListData)client;
1138 /* Send some nice info to the client */
1139 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1140 ("Welcome to the SILC Network %s",
1142 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1143 ("Your host is %s, running version %s",
1144 server->server_name, server_version));
1146 if (server->stat.clients && server->stat.servers + 1)
1147 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1148 ("There are %d clients on %d servers in SILC "
1149 "Network", server->stat.clients,
1150 server->stat.servers + 1));
1151 if (server->stat.cell_clients && server->stat.cell_servers + 1)
1152 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1153 ("There are %d clients on %d server in our cell",
1154 server->stat.cell_clients,
1155 server->stat.cell_servers + 1));
1156 if (server->server_type == SILC_ROUTER) {
1157 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1158 ("I have %d clients, %d channels, %d servers and "
1160 server->stat.my_clients,
1161 server->stat.my_channels,
1162 server->stat.my_servers,
1163 server->stat.my_routers + 1));
1165 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1166 ("I have %d clients and %d channels formed",
1167 server->stat.my_clients,
1168 server->stat.my_channels));
1171 if (server->stat.server_ops || server->stat.router_ops)
1172 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1173 ("There are %d server operators and %d router "
1175 server->stat.server_ops,
1176 server->stat.router_ops));
1177 if (server->stat.my_router_ops + server->stat.my_server_ops)
1178 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1179 ("I have %d operators online",
1180 server->stat.my_router_ops +
1181 server->stat.my_server_ops));
1183 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1184 ("Your connection is secured with %s cipher, "
1185 "key length %d bits",
1186 idata->send_key->cipher->name,
1187 idata->send_key->cipher->key_len));
1188 SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1189 ("Your current nickname is %s",
1193 silc_server_send_motd(server, sock);
1196 /* Kill the client indicated by `remote_client' sending KILLED notify
1197 to the client, to all channels client has joined and to primary
1198 router if needed. The killed client is also removed from all channels. */
1200 void silc_server_kill_client(SilcServer server,
1201 SilcClientEntry remote_client,
1202 const char *comment,
1204 SilcIdType killer_id_type)
1206 SilcBuffer killed, killer;
1208 SILC_LOG_DEBUG(("Killing client %s",
1209 silc_id_render(remote_client->id, SILC_ID_CLIENT)));
1211 /* Send the KILL notify packets. First send it to the channel, then
1212 to our primary router and then directly to the client who is being
1213 killed right now. */
1215 killed = silc_id_payload_encode(remote_client->id, SILC_ID_CLIENT);
1216 killer = silc_id_payload_encode(killer_id, killer_id_type);
1218 /* Send KILLED notify to the channels. It is not sent to the client
1219 as it will be sent differently destined directly to the client and not
1221 silc_server_send_notify_on_channels(server, remote_client,
1222 remote_client, SILC_NOTIFY_TYPE_KILLED,
1223 3, killed->data, killed->len,
1224 comment, comment ? strlen(comment) : 0,
1225 killer->data, killer->len);
1227 /* Send KILLED notify to primary route */
1228 if (!server->standalone)
1229 silc_server_send_notify_killed(server, server->router->connection, TRUE,
1230 remote_client->id, comment,
1231 killer_id, killer_id_type);
1233 /* Send KILLED notify to the client directly */
1234 if (remote_client->connection || remote_client->router)
1235 silc_server_send_notify_killed(server, remote_client->connection ?
1236 remote_client->connection :
1237 remote_client->router->connection, FALSE,
1238 remote_client->id, comment,
1239 killer_id, killer_id_type);
1241 /* Remove the client from all channels. This generates new keys to the
1242 channels as well. */
1243 silc_server_remove_from_channels(server, NULL, remote_client, FALSE,
1246 /* Remove the client entry, If it is locally connected then we will also
1247 disconnect the client here */
1248 if (remote_client->connection) {
1249 /* Remove locally conneted client */
1250 SilcSocketConnection sock = remote_client->connection;
1251 silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
1252 silc_server_close_connection(server, sock);
1254 /* Update statistics */
1255 server->stat.clients--;
1256 server->stat.my_clients--;
1257 if (server->stat.cell_clients)
1258 server->stat.cell_clients--;
1259 SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
1260 SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
1262 /* Remove remote client */
1263 if (!silc_idlist_del_client(server->global_list, remote_client)) {
1264 /* Remove this client from watcher list if it is */
1265 silc_server_del_from_watcher_list(server, remote_client);
1266 silc_idlist_del_client(server->local_list, remote_client);
1270 silc_buffer_free(killer);
1271 silc_buffer_free(killed);
1276 SilcClientEntry client;
1277 SilcNotifyType notify;
1278 const char *new_nick;
1279 } WatcherNotifyContext;
1282 silc_server_check_watcher_list_foreach(void *key, void *context,
1285 WatcherNotifyContext *notify = user_context;
1286 SilcClientEntry entry = context;
1287 SilcSocketConnection sock;
1289 if (entry == notify->client)
1292 sock = silc_server_get_client_route(notify->server, NULL, 0, entry->id,
1295 SILC_LOG_DEBUG(("Sending WATCH notify to %s",
1296 silc_id_render(entry->id, SILC_ID_CLIENT)));
1298 /* Send the WATCH notify */
1299 silc_server_send_notify_watch(notify->server, sock, entry,
1301 notify->new_nick ? notify->new_nick :
1302 (const char *)notify->client->nickname,
1307 /* This function checks whether the `client' nickname is being watched
1308 by someone, and notifies the watcher of the notify change of notify
1309 type indicated by `notify'. */
1311 bool silc_server_check_watcher_list(SilcServer server,
1312 SilcClientEntry client,
1313 const char *new_nick,
1314 SilcNotifyType notify)
1316 unsigned char hash[16];
1317 WatcherNotifyContext n;
1319 SILC_LOG_DEBUG(("Start"));
1321 /* If the watching is rejected by the client do nothing */
1322 if (client->mode & SILC_UMODE_REJECT_WATCHING)
1325 /* Make hash from the nick, or take it from Client ID */
1326 if (client->nickname) {
1328 memset(nick, 0, sizeof(nick));
1329 silc_to_lower(client->nickname, nick, sizeof(nick) - 1);
1330 silc_hash_make(server->md5hash, nick, strlen(nick), hash);
1332 memset(hash, 0, sizeof(hash));
1333 memcpy(hash, client->id->hash, sizeof(client->id->hash));
1338 n.new_nick = new_nick;
1341 /* Send notify to all watchers */
1342 silc_hash_table_find_foreach(server->watcher_list, hash,
1343 silc_server_check_watcher_list_foreach, &n);
1348 /* Remove the `client' from watcher list. After calling this the `client'
1349 is not watching any nicknames. */
1351 bool silc_server_del_from_watcher_list(SilcServer server,
1352 SilcClientEntry client)
1354 SilcHashTableList htl;
1356 SilcClientEntry entry;
1359 silc_hash_table_list(server->watcher_list, &htl);
1360 while (silc_hash_table_get(&htl, &key, (void **)&entry)) {
1361 if (entry == client) {
1362 silc_hash_table_del_by_context(server->watcher_list, key, client);
1364 SILC_LOG_DEBUG(("Removing %s from WATCH list",
1365 silc_id_render(client->id, SILC_ID_CLIENT)));
1367 /* Now check whether there still exists entries with this key, if not
1368 then free the key to not leak memory. */
1369 if (!silc_hash_table_find(server->watcher_list, key, NULL, NULL))
1375 silc_hash_table_list_reset(&htl);
1380 /* Force the client indicated by `chl' to change the channel user mode
1381 on channel indicated by `channel' to `forced_mode'. */
1383 bool silc_server_force_cumode_change(SilcServer server,
1384 SilcSocketConnection sock,
1385 SilcChannelEntry channel,
1386 SilcChannelClientEntry chl,
1387 SilcUInt32 forced_mode)
1389 SilcBuffer idp1, idp2;
1390 unsigned char cumode[4];
1392 SILC_LOG_DEBUG(("Start"));
1394 silc_server_send_notify_cumode(server, sock, FALSE, channel, forced_mode,
1395 server->id, SILC_ID_SERVER,
1396 chl->client->id, NULL);
1398 idp1 = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1399 idp2 = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
1400 SILC_PUT32_MSB(forced_mode, cumode);
1401 silc_server_send_notify_to_channel(server, sock, channel, FALSE,
1402 SILC_NOTIFY_TYPE_CUMODE_CHANGE,
1403 3, idp1->data, idp1->len,
1404 cumode, sizeof(cumode),
1405 idp2->data, idp2->len);
1406 silc_buffer_free(idp1);
1407 silc_buffer_free(idp2);