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;
152 if (!silc_idcache_add(id_list->clients, client->nickname, SILC_ID_CLIENT,
153 (void *)client->id, (void *)client, TRUE)) {
161 /* Free client entry. This free's everything and removes the entry
164 void silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry)
167 /* Remove from cache */
169 silc_idcache_del_by_id(id_list->clients, SILC_ID_CLIENT,
174 silc_free(entry->nickname);
176 silc_free(entry->username);
178 silc_free(entry->userinfo);
180 silc_free(entry->id);
182 silc_cipher_free(entry->send_key);
183 if (entry->receive_key)
184 silc_cipher_free(entry->receive_key);
186 silc_pkcs_free(entry->pkcs);
187 if (entry->public_key)
188 silc_pkcs_public_key_free(entry->public_key);
190 silc_hmac_free(entry->hmac);
194 /* Returns all clients matching requested nickname. Number of clients is
195 returned to `clients_count'. Caller must free the returned table. */
198 silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname,
199 char *server, unsigned int *clients_count)
201 SilcIDCacheList list = NULL;
202 SilcIDCacheEntry id_cache = NULL;
203 SilcClientEntry *clients;
206 if (!silc_idcache_find_by_data(id_list->clients, nickname, &list))
209 clients = silc_calloc(silc_idcache_list_count(list), sizeof(*clients));
212 silc_idcache_list_first(list, &id_cache);
213 clients[i++] = (SilcClientEntry)id_cache->context;
215 while (silc_idcache_list_next(list, &id_cache))
216 clients[i++] = (SilcClientEntry)id_cache->context;
218 silc_idcache_list_free(list);
226 /* Finds client entry by nickname. */
229 silc_idlist_find_client_by_nickname(SilcIDList id_list, char *nickname,
232 SilcIDCacheList list = NULL;
233 SilcIDCacheEntry id_cache = NULL;
234 SilcClientEntry client = NULL;
236 SILC_LOG_DEBUG(("Finding client by nickname"));
239 if (!silc_idcache_find_by_data(id_list->clients, nickname, &list))
243 while (silc_idcache_list_next(list, &id_cache)) {
244 client = (SilcClientEntry)id_cache->context;
246 if (!strcmp(server, XXX, strlen(server)))
253 silc_idcache_list_free(list);
258 if (!silc_idcache_find_by_data_one(id_list->clients, nickname, &id_cache))
261 client = (SilcClientEntry)id_cache->context;
267 /* Finds client by nickname hash. */
270 silc_idlist_find_client_by_hash(SilcIDList id_list, char *nickname,
273 SilcIDCacheList list = NULL;
274 SilcIDCacheEntry id_cache = NULL;
275 SilcClientEntry client = NULL;
276 unsigned char hash[32];
278 SILC_LOG_DEBUG(("Finding client by hash"));
280 silc_hash_make(md5hash, nickname, strlen(nickname), hash);
282 if (!silc_idcache_find_by_id(id_list->clients, SILC_ID_CACHE_ANY,
283 SILC_ID_CLIENT, &list))
286 if (!silc_idcache_list_first(list, &id_cache)) {
287 silc_idcache_list_free(list);
292 client = (SilcClientEntry)id_cache->context;
294 if (client && !SILC_ID_COMPARE_HASH(client->id, hash))
300 if (!silc_idcache_list_next(list, &id_cache))
304 silc_idcache_list_free(list);
309 /* Finds client by Client ID */
312 silc_idlist_find_client_by_id(SilcIDList id_list, SilcClientID *id)
314 SilcIDCacheEntry id_cache = NULL;
315 SilcClientEntry client;
320 SILC_LOG_DEBUG(("Finding client by ID"));
322 if (!silc_idcache_find_by_id_one(id_list->clients, (void *)id,
323 SILC_ID_CLIENT, &id_cache))
326 client = (SilcClientEntry)id_cache->context;
331 /* Replaces old Client ID with new one */
334 silc_idlist_replace_client_id(SilcIDList id_list, SilcClientID *old_id,
335 SilcClientID *new_id)
337 SilcIDCacheEntry id_cache = NULL;
338 SilcClientEntry client;
340 if (!old_id || !new_id)
343 SILC_LOG_DEBUG(("Replacing Client ID"));
345 if (!silc_idcache_find_by_id_one(id_list->clients, (void *)old_id,
346 SILC_ID_CLIENT, &id_cache))
349 client = (SilcClientEntry)id_cache->context;
350 silc_free(client->id);
352 id_cache->id = (void *)new_id;
358 /******************************************************************************
360 Channel entry functions
362 ******************************************************************************/
364 /* Add new channel entry. This add the new channel entry to the ID cache
365 system and returns the allocated entry or NULL on error. */
368 silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode,
369 SilcChannelID *id, SilcServerEntry router,
370 SilcCipher channel_key)
372 SilcChannelEntry channel;
374 channel = silc_calloc(1, sizeof(*channel));
375 channel->channel_name = channel_name;
376 channel->mode = mode;
378 channel->router = router;
379 channel->channel_key = channel_key;
380 silc_list_init(channel->user_list, struct SilcChannelClientEntryStruct,
383 if (!silc_idcache_add(id_list->channels, channel->channel_name,
384 SILC_ID_CHANNEL, (void *)channel->id,
385 (void *)channel, TRUE)) {
393 /* Free channel entry. This free's everything. */
395 void silc_idlist_del_channel(SilcIDList id_list, SilcChannelEntry entry)
398 SilcChannelClientEntry chl;
400 /* Remove from cache */
402 silc_idcache_del_by_id(id_list->channels, SILC_ID_CHANNEL,
406 if (entry->channel_name)
407 silc_free(entry->channel_name);
409 silc_free(entry->id);
411 silc_free(entry->topic);
412 if (entry->channel_key)
413 silc_cipher_free(entry->channel_key);
415 memset(entry->key, 0, entry->key_len / 8);
416 silc_free(entry->key);
418 memset(entry->iv, 0, sizeof(entry->iv));
420 silc_list_start(entry->user_list);
421 while ((chl = silc_list_get(entry->user_list)) != SILC_LIST_END) {
422 silc_list_del(entry->user_list, chl);
428 /* Finds channel by channel name. Channel names are unique and they
429 are not case-sensitive. */
432 silc_idlist_find_channel_by_name(SilcIDList id_list, char *name)
434 SilcIDCacheList list = NULL;
435 SilcIDCacheEntry id_cache = NULL;
436 SilcChannelEntry channel;
438 SILC_LOG_DEBUG(("Finding channel by name"));
440 if (!silc_idcache_find_by_data_loose(id_list->channels, name, &list))
443 if (!silc_idcache_list_first(list, &id_cache)) {
444 silc_idcache_list_free(list);
448 channel = (SilcChannelEntry)id_cache->context;
450 silc_idcache_list_free(list);
455 /* Finds channel by Channel ID. */
458 silc_idlist_find_channel_by_id(SilcIDList id_list, SilcChannelID *id)
460 SilcIDCacheEntry id_cache = NULL;
461 SilcChannelEntry channel;
466 SILC_LOG_DEBUG(("Finding channel by ID"));
468 if (!silc_idcache_find_by_id_one(id_list->channels, (void *)id,
469 SILC_ID_CHANNEL, &id_cache))
472 channel = (SilcChannelEntry)id_cache->context;