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 /******************************************************************************
27 Server entry functions
29 ******************************************************************************/
31 /* Add new server entry. This adds the new server entry to ID cache and
32 returns the allocated entry object or NULL on error. This is called
33 when new server connects to us. We also add ourselves to cache with
37 silc_idlist_add_server(SilcIDList id_list,
38 char *server_name, int server_type,
39 SilcServerID *id, SilcServerEntry router,
40 SilcCipher send_key, SilcCipher receive_key,
41 SilcPKCS pkcs, SilcHmac hmac,
42 SilcPublicKey public_key, void *connection)
44 SilcServerEntry server;
46 SILC_LOG_DEBUG(("Adding new server entry"));
48 server = silc_calloc(1, sizeof(*server));
49 server->server_name = server_name;
50 server->server_type = server_type;
52 server->router = router;
53 server->send_key = send_key;
54 server->receive_key = receive_key;
57 server->public_key = public_key;
58 server->connection = connection;
60 if (!silc_idcache_add(id_list->servers, server->server_name, SILC_ID_SERVER,
61 (void *)server->id, (void *)server, TRUE)) {
69 /* Finds server by Server ID */
72 silc_idlist_find_server_by_id(SilcIDList id_list, SilcServerID *id)
74 SilcIDCacheEntry id_cache = NULL;
75 SilcServerEntry server;
80 SILC_LOG_DEBUG(("Finding server by ID"));
82 if (!silc_idcache_find_by_id_one(id_list->servers, (void *)id,
83 SILC_ID_SERVER, &id_cache))
86 server = (SilcServerEntry)id_cache->context;
91 /* Replaces old Server ID with new one */
94 silc_idlist_replace_server_id(SilcIDList id_list, SilcServerID *old_id,
97 SilcIDCacheEntry id_cache = NULL;
98 SilcServerEntry server;
100 if (!old_id || !new_id)
103 SILC_LOG_DEBUG(("Replacing Server ID"));
105 if (!silc_idcache_find_by_id_one(id_list->servers, (void *)old_id,
106 SILC_ID_SERVER, &id_cache))
109 server = (SilcServerEntry)id_cache->context;
110 silc_free(server->id);
112 id_cache->id = (void *)new_id;
117 /******************************************************************************
119 Client entry functions
121 ******************************************************************************/
123 /* Add new client entry. This adds the client entry to ID cache system
124 and returns the allocated client entry or NULL on error. This is
125 called when new client connection is accepted to the server. */
128 silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username,
129 char *userinfo, SilcClientID *id,
130 SilcServerEntry router,
131 SilcCipher send_key, SilcCipher receive_key,
132 SilcPKCS pkcs, SilcHmac hmac,
133 SilcPublicKey public_key, void *connection)
135 SilcClientEntry client;
137 SILC_LOG_DEBUG(("Adding new client entry"));
139 client = silc_calloc(1, sizeof(*client));
140 client->nickname = nickname;
141 client->username = username;
142 client->userinfo = userinfo;
144 client->router = router;
145 client->send_key = send_key;
146 client->receive_key = receive_key;
149 client->public_key = public_key;
150 client->connection = connection;
151 silc_list_init(client->channels, struct SilcChannelClientEntryStruct,
154 if (!silc_idcache_add(id_list->clients, client->nickname, SILC_ID_CLIENT,
155 (void *)client->id, (void *)client, TRUE)) {
163 /* Free client entry. This free's everything and removes the entry
166 void silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry)
169 /* Remove from cache */
171 silc_idcache_del_by_id(id_list->clients, SILC_ID_CLIENT,
176 silc_free(entry->nickname);
178 silc_free(entry->username);
180 silc_free(entry->userinfo);
182 silc_free(entry->id);
184 silc_cipher_free(entry->send_key);
185 if (entry->receive_key)
186 silc_cipher_free(entry->receive_key);
188 silc_pkcs_free(entry->pkcs);
189 if (entry->public_key)
190 silc_pkcs_public_key_free(entry->public_key);
192 silc_hmac_free(entry->hmac);
196 /* Returns all clients matching requested nickname. Number of clients is
197 returned to `clients_count'. Caller must free the returned table. */
200 silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname,
201 char *server, unsigned int *clients_count)
203 SilcIDCacheList list = NULL;
204 SilcIDCacheEntry id_cache = NULL;
205 SilcClientEntry *clients;
208 if (!silc_idcache_find_by_data(id_list->clients, nickname, &list))
211 clients = silc_calloc(silc_idcache_list_count(list), sizeof(*clients));
214 silc_idcache_list_first(list, &id_cache);
215 clients[i++] = (SilcClientEntry)id_cache->context;
217 while (silc_idcache_list_next(list, &id_cache))
218 clients[i++] = (SilcClientEntry)id_cache->context;
220 silc_idcache_list_free(list);
228 /* Finds client entry by nickname. */
231 silc_idlist_find_client_by_nickname(SilcIDList id_list, char *nickname,
234 SilcIDCacheList list = NULL;
235 SilcIDCacheEntry id_cache = NULL;
236 SilcClientEntry client = NULL;
238 SILC_LOG_DEBUG(("Finding client by nickname"));
241 if (!silc_idcache_find_by_data(id_list->clients, nickname, &list))
245 while (silc_idcache_list_next(list, &id_cache)) {
246 client = (SilcClientEntry)id_cache->context;
248 if (!strcmp(server, XXX, strlen(server)))
255 silc_idcache_list_free(list);
260 if (!silc_idcache_find_by_data_one(id_list->clients, nickname, &id_cache))
263 client = (SilcClientEntry)id_cache->context;
269 /* Finds client by nickname hash. */
272 silc_idlist_find_client_by_hash(SilcIDList id_list, char *nickname,
275 SilcIDCacheList list = NULL;
276 SilcIDCacheEntry id_cache = NULL;
277 SilcClientEntry client = NULL;
278 unsigned char hash[32];
280 SILC_LOG_DEBUG(("Finding client by hash"));
282 silc_hash_make(md5hash, nickname, strlen(nickname), hash);
284 if (!silc_idcache_find_by_id(id_list->clients, SILC_ID_CACHE_ANY,
285 SILC_ID_CLIENT, &list))
288 if (!silc_idcache_list_first(list, &id_cache)) {
289 silc_idcache_list_free(list);
294 client = (SilcClientEntry)id_cache->context;
296 if (client && !SILC_ID_COMPARE_HASH(client->id, hash))
302 if (!silc_idcache_list_next(list, &id_cache))
306 silc_idcache_list_free(list);
311 /* Finds client by Client ID */
314 silc_idlist_find_client_by_id(SilcIDList id_list, SilcClientID *id)
316 SilcIDCacheEntry id_cache = NULL;
317 SilcClientEntry client;
322 SILC_LOG_DEBUG(("Finding client by ID"));
324 if (!silc_idcache_find_by_id_one(id_list->clients, (void *)id,
325 SILC_ID_CLIENT, &id_cache))
328 client = (SilcClientEntry)id_cache->context;
333 /* Replaces old Client ID with new one */
336 silc_idlist_replace_client_id(SilcIDList id_list, SilcClientID *old_id,
337 SilcClientID *new_id)
339 SilcIDCacheEntry id_cache = NULL;
340 SilcClientEntry client;
342 if (!old_id || !new_id)
345 SILC_LOG_DEBUG(("Replacing Client ID"));
347 if (!silc_idcache_find_by_id_one(id_list->clients, (void *)old_id,
348 SILC_ID_CLIENT, &id_cache))
351 client = (SilcClientEntry)id_cache->context;
352 silc_free(client->id);
354 id_cache->id = (void *)new_id;
360 /******************************************************************************
362 Channel entry functions
364 ******************************************************************************/
366 /* Add new channel entry. This add the new channel entry to the ID cache
367 system and returns the allocated entry or NULL on error. */
370 silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode,
371 SilcChannelID *id, SilcServerEntry router,
372 SilcCipher channel_key)
374 SilcChannelEntry channel;
376 channel = silc_calloc(1, sizeof(*channel));
377 channel->channel_name = channel_name;
378 channel->mode = mode;
380 channel->router = router;
381 channel->channel_key = channel_key;
382 silc_list_init(channel->user_list, struct SilcChannelClientEntryStruct,
385 if (!silc_idcache_add(id_list->channels, channel->channel_name,
386 SILC_ID_CHANNEL, (void *)channel->id,
387 (void *)channel, TRUE)) {
395 /* Free channel entry. This free's everything. */
397 void silc_idlist_del_channel(SilcIDList id_list, SilcChannelEntry entry)
400 SilcChannelClientEntry chl;
402 /* Remove from cache */
404 silc_idcache_del_by_id(id_list->channels, SILC_ID_CHANNEL,
408 if (entry->channel_name)
409 silc_free(entry->channel_name);
411 silc_free(entry->id);
413 silc_free(entry->topic);
414 if (entry->channel_key)
415 silc_cipher_free(entry->channel_key);
417 memset(entry->key, 0, entry->key_len / 8);
418 silc_free(entry->key);
420 memset(entry->iv, 0, sizeof(entry->iv));
422 silc_list_start(entry->user_list);
423 while ((chl = silc_list_get(entry->user_list)) != SILC_LIST_END) {
424 silc_list_del(entry->user_list, chl);
430 /* Finds channel by channel name. Channel names are unique and they
431 are not case-sensitive. */
434 silc_idlist_find_channel_by_name(SilcIDList id_list, char *name)
436 SilcIDCacheList list = NULL;
437 SilcIDCacheEntry id_cache = NULL;
438 SilcChannelEntry channel;
440 SILC_LOG_DEBUG(("Finding channel by name"));
442 if (!silc_idcache_find_by_data_loose(id_list->channels, name, &list))
445 if (!silc_idcache_list_first(list, &id_cache)) {
446 silc_idcache_list_free(list);
450 channel = (SilcChannelEntry)id_cache->context;
452 silc_idcache_list_free(list);
457 /* Finds channel by Channel ID. */
460 silc_idlist_find_channel_by_id(SilcIDList id_list, SilcChannelID *id)
462 SilcIDCacheEntry id_cache = NULL;
463 SilcChannelEntry channel;
468 SILC_LOG_DEBUG(("Finding channel by ID"));
470 if (!silc_idcache_find_by_id_one(id_list->channels, (void *)id,
471 SILC_ID_CHANNEL, &id_cache))
474 channel = (SilcChannelEntry)id_cache->context;