5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2000 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; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
23 * Revision 1.8 2000/10/06 08:10:23 priikone
24 * Added WHOIS to send multiple replies if multiple nicknames are
26 * Added MOTD command and [motd] config section and server also sends
27 * motd to client on connection now.
28 * Fixed TOPIC command some more.
30 * Revision 1.7 2000/07/26 07:04:01 priikone
31 * Added server_find_by_id, replace_[server/client]_id.
33 * Revision 1.6 2000/07/17 11:47:30 priikone
34 * Added command lagging support. Added idle counting support.
36 * Revision 1.5 2000/07/12 05:59:41 priikone
37 * Major rewrite of ID Cache system. Support added for the new
38 * ID cache system. Major rewrite of ID List stuff on server. All
39 * SilcXXXList's are now called SilcXXXEntry's and they are pointers
40 * by default. A lot rewritten ID list functions.
42 * Revision 1.4 2000/07/06 07:16:13 priikone
43 * Added SilcPublicKey's
45 * Revision 1.3 2000/07/05 06:14:01 priikone
46 * Global costemic changes.
48 * Revision 1.2 2000/07/03 05:52:11 priikone
49 * Fixed typo and a bug.
51 * Revision 1.1.1.1 2000/06/27 11:36:56 priikone
52 * Imported from internal CVS/Added Log headers.
57 #include "serverincludes.h"
60 /******************************************************************************
62 Server entry functions
64 ******************************************************************************/
66 /* Add new server entry. This adds the new server entry to ID cache and
67 returns the allocated entry object or NULL on error. This is called
68 when new server connects to us. We also add ourselves to cache with
72 silc_idlist_add_server(SilcIDList id_list,
73 char *server_name, int server_type,
74 SilcServerID *id, SilcServerEntry router,
75 SilcCipher send_key, SilcCipher receive_key,
76 SilcPKCS pkcs, SilcHmac hmac,
77 SilcPublicKey public_key, void *connection)
79 SilcServerEntry server;
81 SILC_LOG_DEBUG(("Adding new server entry"));
83 server = silc_calloc(1, sizeof(*server));
84 server->server_name = server_name;
85 server->server_type = server_type;
87 server->router = router;
88 server->send_key = send_key;
89 server->receive_key = receive_key;
92 server->public_key = public_key;
93 server->connection = connection;
95 if (!silc_idcache_add(id_list->servers, server->server_name, SILC_ID_SERVER,
96 (void *)server->id, (void *)server, TRUE)) {
104 /* Finds server by Server ID */
107 silc_idlist_find_server_by_id(SilcIDList id_list, SilcServerID *id)
109 SilcIDCacheEntry id_cache = NULL;
110 SilcServerEntry server;
115 SILC_LOG_DEBUG(("Finding server by ID"));
117 if (!silc_idcache_find_by_id_one(id_list->servers, (void *)id,
118 SILC_ID_SERVER, &id_cache))
121 server = (SilcServerEntry)id_cache->context;
126 /* Replaces old Server ID with new one */
129 silc_idlist_replace_server_id(SilcIDList id_list, SilcServerID *old_id,
130 SilcServerID *new_id)
132 SilcIDCacheEntry id_cache = NULL;
133 SilcServerEntry server;
135 if (!old_id || !new_id)
138 SILC_LOG_DEBUG(("Replacing Server ID"));
140 if (!silc_idcache_find_by_id_one(id_list->servers, (void *)old_id,
141 SILC_ID_SERVER, &id_cache))
144 server = (SilcServerEntry)id_cache->context;
145 silc_free(server->id);
147 id_cache->id = (void *)new_id;
152 /******************************************************************************
154 Client entry functions
156 ******************************************************************************/
158 /* Add new client entry. This adds the client entry to ID cache system
159 and returns the allocated client entry or NULL on error. This is
160 called when new client connection is accepted to the server. */
163 silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username,
164 char *userinfo, SilcClientID *id,
165 SilcServerEntry router,
166 SilcCipher send_key, SilcCipher receive_key,
167 SilcPKCS pkcs, SilcHmac hmac,
168 SilcPublicKey public_key, void *connection)
170 SilcClientEntry client;
172 SILC_LOG_DEBUG(("Adding new client entry"));
174 client = silc_calloc(1, sizeof(*client));
175 client->nickname = nickname;
176 client->username = username;
177 client->userinfo = userinfo;
179 client->router = router;
180 client->send_key = send_key;
181 client->receive_key = receive_key;
184 client->public_key = public_key;
185 client->connection = connection;
187 if (!silc_idcache_add(id_list->clients, client->nickname, SILC_ID_CLIENT,
188 (void *)client->id, (void *)client, TRUE)) {
196 /* Free client entry. This free's everything and removes the entry
199 void silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry)
202 /* Remove from cache */
204 silc_idcache_del_by_id(id_list->clients, SILC_ID_CLIENT,
209 silc_free(entry->nickname);
211 silc_free(entry->username);
213 silc_free(entry->userinfo);
215 silc_free(entry->id);
217 silc_cipher_free(entry->send_key);
218 if (entry->receive_key)
219 silc_cipher_free(entry->receive_key);
221 silc_pkcs_free(entry->pkcs);
222 if (entry->public_key)
223 silc_pkcs_public_key_free(entry->public_key);
225 silc_hmac_free(entry->hmac);
229 /* Returns all clients matching requested nickname. Number of clients is
230 returned to `clients_count'. Caller must free the returned table. */
233 silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname,
234 char *server, unsigned int *clients_count)
236 SilcIDCacheList list = NULL;
237 SilcIDCacheEntry id_cache = NULL;
238 SilcClientEntry *clients;
241 if (!silc_idcache_find_by_data(id_list->clients, nickname, &list))
244 clients = silc_calloc(silc_idcache_list_count(list), sizeof(*clients));
247 silc_idcache_list_first(list, &id_cache);
248 clients[i++] = (SilcClientEntry)id_cache->context;
250 while (silc_idcache_list_next(list, &id_cache))
251 clients[i++] = (SilcClientEntry)id_cache->context;
253 silc_idcache_list_free(list);
261 /* Finds client entry by nickname. */
264 silc_idlist_find_client_by_nickname(SilcIDList id_list, char *nickname,
267 SilcIDCacheList list = NULL;
268 SilcIDCacheEntry id_cache = NULL;
269 SilcClientEntry client = NULL;
271 SILC_LOG_DEBUG(("Finding client by nickname"));
274 if (!silc_idcache_find_by_data(id_list->clients, nickname, &list))
278 while (silc_idcache_list_next(list, &id_cache)) {
279 client = (SilcClientEntry)id_cache->context;
281 if (!strcmp(server, XXX, strlen(server)))
288 silc_idcache_list_free(list);
293 if (!silc_idcache_find_by_data_one(id_list->clients, nickname, &id_cache))
296 client = (SilcClientEntry)id_cache->context;
302 /* Finds client by nickname hash. */
305 silc_idlist_find_client_by_hash(SilcIDList id_list, char *nickname,
308 SilcIDCacheList list = NULL;
309 SilcIDCacheEntry id_cache = NULL;
310 SilcClientEntry client = NULL;
311 unsigned char hash[32];
313 SILC_LOG_DEBUG(("Finding client by hash"));
315 silc_hash_make(md5hash, nickname, strlen(nickname), hash);
317 if (!silc_idcache_find_by_id(id_list->clients, SILC_ID_CACHE_ANY,
318 SILC_ID_CLIENT, &list))
321 if (!silc_idcache_list_first(list, &id_cache)) {
322 silc_idcache_list_free(list);
327 client = (SilcClientEntry)id_cache->context;
329 if (client && !SILC_ID_COMPARE_HASH(client->id, hash))
335 if (!silc_idcache_list_next(list, &id_cache))
339 silc_idcache_list_free(list);
344 /* Finds client by Client ID */
347 silc_idlist_find_client_by_id(SilcIDList id_list, SilcClientID *id)
349 SilcIDCacheEntry id_cache = NULL;
350 SilcClientEntry client;
355 SILC_LOG_DEBUG(("Finding client by ID"));
357 if (!silc_idcache_find_by_id_one(id_list->clients, (void *)id,
358 SILC_ID_CLIENT, &id_cache))
361 client = (SilcClientEntry)id_cache->context;
366 /* Replaces old Client ID with new one */
369 silc_idlist_replace_client_id(SilcIDList id_list, SilcClientID *old_id,
370 SilcClientID *new_id)
372 SilcIDCacheEntry id_cache = NULL;
373 SilcClientEntry client;
375 if (!old_id || !new_id)
378 SILC_LOG_DEBUG(("Replacing Client ID"));
380 if (!silc_idcache_find_by_id_one(id_list->clients, (void *)old_id,
381 SILC_ID_CLIENT, &id_cache))
384 client = (SilcClientEntry)id_cache->context;
385 silc_free(client->id);
387 id_cache->id = (void *)new_id;
393 /******************************************************************************
395 Channel entry functions
397 ******************************************************************************/
399 /* Add new channel entry. This add the new channel entry to the ID cache
400 system and returns the allocated entry or NULL on error. */
403 silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode,
404 SilcChannelID *id, SilcServerEntry router,
405 SilcCipher channel_key)
407 SilcChannelEntry channel;
409 channel = silc_calloc(1, sizeof(*channel));
410 channel->channel_name = channel_name;
411 channel->mode = mode;
413 channel->router = router;
414 channel->channel_key = channel_key;
416 if (!silc_idcache_add(id_list->channels, channel->channel_name,
417 SILC_ID_CHANNEL, (void *)channel->id,
418 (void *)channel, TRUE)) {
426 /* Free channel entry. This free's everything. */
428 void silc_idlist_del_channel(SilcIDList id_list, SilcChannelEntry entry)
431 /* Remove from cache */
433 silc_idcache_del_by_id(id_list->channels, SILC_ID_CHANNEL,
437 if (entry->channel_name)
438 silc_free(entry->channel_name);
440 silc_free(entry->id);
442 silc_free(entry->topic);
443 if (entry->channel_key)
444 silc_cipher_free(entry->channel_key);
446 memset(entry->key, 0, entry->key_len / 8);
447 silc_free(entry->key);
449 memset(entry->iv, 0, sizeof(entry->iv));
451 if (entry->user_list_count)
452 silc_free(entry->user_list);
456 /* Finds channel by channel name. Channel names are unique and they
457 are not case-sensitive. */
460 silc_idlist_find_channel_by_name(SilcIDList id_list, char *name)
462 SilcIDCacheList list = NULL;
463 SilcIDCacheEntry id_cache = NULL;
464 SilcChannelEntry channel;
466 SILC_LOG_DEBUG(("Finding channel by name"));
468 if (!silc_idcache_find_by_data_loose(id_list->channels, name, &list))
471 if (!silc_idcache_list_first(list, &id_cache)) {
472 silc_idcache_list_free(list);
476 channel = (SilcChannelEntry)id_cache->context;
478 silc_idcache_list_free(list);
483 /* Finds channel by Channel ID. */
486 silc_idlist_find_channel_by_id(SilcIDList id_list, SilcChannelID *id)
488 SilcIDCacheEntry id_cache = NULL;
489 SilcChannelEntry channel;
494 SILC_LOG_DEBUG(("Finding channel by ID"));
496 if (!silc_idcache_find_by_id_one(id_list->channels, (void *)id,
497 SILC_ID_CHANNEL, &id_cache))
500 channel = (SilcChannelEntry)id_cache->context;