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.
22 #include "serverincludes.h"
25 /******************************************************************************
29 ******************************************************************************/
31 /* This function is used to add keys and stuff to common ID entry data
34 void silc_idlist_add_data(void *entry, SilcIDListData idata)
36 SilcIDListData data = (SilcIDListData)entry;
37 data->send_key = idata->send_key;
38 data->receive_key = idata->receive_key;
39 data->hmac = idata->hmac;
40 data->hmac_key = idata->hmac_key;
41 data->hmac_key_len = idata->hmac_key_len;
42 data->pkcs = idata->pkcs;
43 data->public_key = idata->public_key;
44 data->last_receive = idata->last_receive;
45 data->last_sent = idata->last_sent;
46 data->registered = idata->registered;
49 /* Free's all data in the common ID entry data structure. */
51 void silc_idlist_del_data(void *entry)
53 SilcIDListData idata = (SilcIDListData)entry;
55 silc_cipher_free(idata->send_key);
56 if (idata->receive_key)
57 silc_cipher_free(idata->receive_key);
59 silc_hmac_free(idata->hmac);
60 if (idata->hmac_key) {
61 memset(idata->hmac_key, 0, idata->hmac_key_len);
62 silc_free(idata->hmac_key);
65 silc_pkcs_free(idata->pkcs);
66 if (idata->public_key)
67 silc_pkcs_public_key_free(idata->public_key);
70 /******************************************************************************
72 Server entry functions
74 ******************************************************************************/
76 /* Add new server entry. This adds the new server entry to ID cache and
77 returns the allocated entry object or NULL on error. This is called
78 when new server connects to us. We also add ourselves to cache with
82 silc_idlist_add_server(SilcIDList id_list,
83 char *server_name, int server_type,
84 SilcServerID *id, SilcServerEntry router,
87 SilcServerEntry server;
89 SILC_LOG_DEBUG(("Adding new server entry"));
91 server = silc_calloc(1, sizeof(*server));
92 server->server_name = server_name;
93 server->server_type = server_type;
95 server->router = router;
96 server->connection = connection;
98 if (!silc_idcache_add(id_list->servers, server->server_name, SILC_ID_SERVER,
99 (void *)server->id, (void *)server, TRUE)) {
107 /* Finds server by Server ID */
110 silc_idlist_find_server_by_id(SilcIDList id_list, SilcServerID *id)
112 SilcIDCacheEntry id_cache = NULL;
113 SilcServerEntry server;
118 SILC_LOG_DEBUG(("Finding server by ID"));
120 if (!silc_idcache_find_by_id_one(id_list->servers, (void *)id,
121 SILC_ID_SERVER, &id_cache))
124 server = (SilcServerEntry)id_cache->context;
129 /* Replaces old Server ID with new one */
132 silc_idlist_replace_server_id(SilcIDList id_list, SilcServerID *old_id,
133 SilcServerID *new_id)
135 SilcIDCacheEntry id_cache = NULL;
136 SilcServerEntry server;
138 if (!old_id || !new_id)
141 SILC_LOG_DEBUG(("Replacing Server ID"));
143 if (!silc_idcache_find_by_id_one(id_list->servers, (void *)old_id,
144 SILC_ID_SERVER, &id_cache))
147 server = (SilcServerEntry)id_cache->context;
148 silc_free(server->id);
150 id_cache->id = (void *)new_id;
155 /******************************************************************************
157 Client entry functions
159 ******************************************************************************/
161 /* Add new client entry. This adds the client entry to ID cache system
162 and returns the allocated client entry or NULL on error. This is
163 called when new client connection is accepted to the server. */
166 silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username,
167 char *userinfo, SilcClientID *id,
168 SilcServerEntry router, 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->connection = connection;
181 silc_list_init(client->channels, struct SilcChannelClientEntryStruct,
184 if (!silc_idcache_add(id_list->clients, client->nickname, SILC_ID_CLIENT,
185 (void *)client->id, (void *)client, TRUE)) {
193 /* Free client entry. This free's everything and removes the entry
194 from ID cache. Call silc_idlist_del_data before calling this one. */
196 void silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry)
199 /* Remove from cache */
201 silc_idcache_del_by_id(id_list->clients, SILC_ID_CLIENT,
206 silc_free(entry->nickname);
208 silc_free(entry->username);
210 silc_free(entry->userinfo);
212 silc_free(entry->id);
216 /* Returns all clients matching requested nickname. Number of clients is
217 returned to `clients_count'. Caller must free the returned table. */
220 silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname,
221 char *server, unsigned int *clients_count)
223 SilcIDCacheList list = NULL;
224 SilcIDCacheEntry id_cache = NULL;
225 SilcClientEntry *clients;
228 if (!silc_idcache_find_by_data(id_list->clients, nickname, &list))
231 clients = silc_calloc(silc_idcache_list_count(list), sizeof(*clients));
234 silc_idcache_list_first(list, &id_cache);
235 clients[i++] = (SilcClientEntry)id_cache->context;
237 while (silc_idcache_list_next(list, &id_cache))
238 clients[i++] = (SilcClientEntry)id_cache->context;
240 silc_idcache_list_free(list);
248 /* Finds client entry by nickname. */
251 silc_idlist_find_client_by_nickname(SilcIDList id_list, char *nickname,
254 SilcIDCacheList list = NULL;
255 SilcIDCacheEntry id_cache = NULL;
256 SilcClientEntry client = NULL;
258 SILC_LOG_DEBUG(("Finding client by nickname"));
261 if (!silc_idcache_find_by_data(id_list->clients, nickname, &list))
265 while (silc_idcache_list_next(list, &id_cache)) {
266 client = (SilcClientEntry)id_cache->context;
268 if (!strcmp(server, XXX, strlen(server)))
275 silc_idcache_list_free(list);
280 if (!silc_idcache_find_by_data_one(id_list->clients, nickname, &id_cache))
283 client = (SilcClientEntry)id_cache->context;
289 /* Finds client by nickname hash. */
292 silc_idlist_find_client_by_hash(SilcIDList id_list, char *nickname,
295 SilcIDCacheList list = NULL;
296 SilcIDCacheEntry id_cache = NULL;
297 SilcClientEntry client = NULL;
298 unsigned char hash[32];
300 SILC_LOG_DEBUG(("Finding client by hash"));
302 silc_hash_make(md5hash, nickname, strlen(nickname), hash);
304 if (!silc_idcache_find_by_id(id_list->clients, SILC_ID_CACHE_ANY,
305 SILC_ID_CLIENT, &list))
308 if (!silc_idcache_list_first(list, &id_cache)) {
309 silc_idcache_list_free(list);
314 client = (SilcClientEntry)id_cache->context;
316 if (client && !SILC_ID_COMPARE_HASH(client->id, hash))
322 if (!silc_idcache_list_next(list, &id_cache))
326 silc_idcache_list_free(list);
331 /* Finds client by Client ID */
334 silc_idlist_find_client_by_id(SilcIDList id_list, SilcClientID *id)
336 SilcIDCacheEntry id_cache = NULL;
337 SilcClientEntry client;
342 SILC_LOG_DEBUG(("Finding client by ID"));
344 if (!silc_idcache_find_by_id_one(id_list->clients, (void *)id,
345 SILC_ID_CLIENT, &id_cache))
348 client = (SilcClientEntry)id_cache->context;
353 /* Replaces old Client ID with new one */
356 silc_idlist_replace_client_id(SilcIDList id_list, SilcClientID *old_id,
357 SilcClientID *new_id)
359 SilcIDCacheEntry id_cache = NULL;
360 SilcClientEntry client;
362 if (!old_id || !new_id)
365 SILC_LOG_DEBUG(("Replacing Client ID"));
367 if (!silc_idcache_find_by_id_one(id_list->clients, (void *)old_id,
368 SILC_ID_CLIENT, &id_cache))
371 client = (SilcClientEntry)id_cache->context;
372 silc_free(client->id);
374 id_cache->id = (void *)new_id;
380 /******************************************************************************
382 Channel entry functions
384 ******************************************************************************/
386 /* Add new channel entry. This add the new channel entry to the ID cache
387 system and returns the allocated entry or NULL on error. */
390 silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode,
391 SilcChannelID *id, SilcServerEntry router,
392 SilcCipher channel_key)
394 SilcChannelEntry channel;
396 channel = silc_calloc(1, sizeof(*channel));
397 channel->channel_name = channel_name;
398 channel->mode = mode;
400 channel->router = router;
401 channel->channel_key = channel_key;
402 silc_list_init(channel->user_list, struct SilcChannelClientEntryStruct,
405 if (!silc_idcache_add(id_list->channels, channel->channel_name,
406 SILC_ID_CHANNEL, (void *)channel->id,
407 (void *)channel, TRUE)) {
415 /* Free channel entry. This free's everything. */
417 void silc_idlist_del_channel(SilcIDList id_list, SilcChannelEntry entry)
420 SilcChannelClientEntry chl;
422 /* Remove from cache */
424 silc_idcache_del_by_id(id_list->channels, SILC_ID_CHANNEL,
428 if (entry->channel_name)
429 silc_free(entry->channel_name);
431 silc_free(entry->id);
433 silc_free(entry->topic);
434 if (entry->channel_key)
435 silc_cipher_free(entry->channel_key);
437 memset(entry->key, 0, entry->key_len / 8);
438 silc_free(entry->key);
440 memset(entry->iv, 0, sizeof(entry->iv));
442 silc_list_start(entry->user_list);
443 while ((chl = silc_list_get(entry->user_list)) != SILC_LIST_END) {
444 silc_list_del(entry->user_list, chl);
450 /* Finds channel by channel name. Channel names are unique and they
451 are not case-sensitive. */
454 silc_idlist_find_channel_by_name(SilcIDList id_list, char *name)
456 SilcIDCacheList list = NULL;
457 SilcIDCacheEntry id_cache = NULL;
458 SilcChannelEntry channel;
460 SILC_LOG_DEBUG(("Finding channel by name"));
462 if (!silc_idcache_find_by_data_loose(id_list->channels, name, &list))
465 if (!silc_idcache_list_first(list, &id_cache)) {
466 silc_idcache_list_free(list);
470 channel = (SilcChannelEntry)id_cache->context;
472 silc_idcache_list_free(list);
477 /* Finds channel by Channel ID. */
480 silc_idlist_find_channel_by_id(SilcIDList id_list, SilcChannelID *id)
482 SilcIDCacheEntry id_cache = NULL;
483 SilcChannelEntry channel;
488 SILC_LOG_DEBUG(("Finding channel by ID"));
490 if (!silc_idcache_find_by_id_one(id_list->channels, (void *)id,
491 SILC_ID_CHANNEL, &id_cache))
494 channel = (SilcChannelEntry)id_cache->context;