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,
111 SilcIDCacheEntry *ret_entry)
113 SilcIDCacheEntry id_cache = NULL;
114 SilcServerEntry server;
119 SILC_LOG_DEBUG(("Finding server by ID"));
121 if (!silc_idcache_find_by_id_one(id_list->servers, (void *)id,
122 SILC_ID_SERVER, &id_cache))
125 server = (SilcServerEntry)id_cache->context;
128 *ret_entry = id_cache;
133 /* Replaces old Server ID with new one */
136 silc_idlist_replace_server_id(SilcIDList id_list, SilcServerID *old_id,
137 SilcServerID *new_id)
139 SilcIDCacheEntry id_cache = NULL;
140 SilcServerEntry server;
142 if (!old_id || !new_id)
145 SILC_LOG_DEBUG(("Replacing Server ID"));
147 if (!silc_idcache_find_by_id_one(id_list->servers, (void *)old_id,
148 SILC_ID_SERVER, &id_cache))
151 server = (SilcServerEntry)id_cache->context;
152 silc_free(server->id);
154 id_cache->id = (void *)new_id;
159 /* Removes and free's server entry from ID list */
161 void silc_idlist_del_server(SilcIDList id_list, SilcServerEntry entry)
164 /* Remove from cache */
166 silc_idcache_del_by_id(id_list->servers, SILC_ID_SERVER,
170 if (entry->server_name)
171 silc_free(entry->server_name);
173 silc_free(entry->id);
177 /******************************************************************************
179 Client entry functions
181 ******************************************************************************/
183 /* Add new client entry. This adds the client entry to ID cache system
184 and returns the allocated client entry or NULL on error. This is
185 called when new client connection is accepted to the server. */
188 silc_idlist_add_client(SilcIDList id_list, unsigned char *nickname,
189 char *username, char *userinfo, SilcClientID *id,
190 SilcServerEntry router, void *connection)
192 SilcClientEntry client;
194 SILC_LOG_DEBUG(("Adding new client entry"));
196 client = silc_calloc(1, sizeof(*client));
197 client->nickname = nickname;
198 client->username = username;
199 client->userinfo = userinfo;
201 client->router = router;
202 client->connection = connection;
203 silc_list_init(client->channels, struct SilcChannelClientEntryStruct,
206 if (!silc_idcache_add(id_list->clients, nickname, SILC_ID_CLIENT,
207 (void *)client->id, (void *)client, TRUE)) {
215 /* Free client entry. This free's everything and removes the entry
216 from ID cache. Call silc_idlist_del_data before calling this one. */
218 void silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry)
221 /* Remove from cache */
223 silc_idcache_del_by_id(id_list->clients, SILC_ID_CLIENT,
228 silc_free(entry->nickname);
230 silc_free(entry->username);
232 silc_free(entry->userinfo);
234 silc_free(entry->id);
238 /* Returns all clients matching requested nickname. Number of clients is
239 returned to `clients_count'. Caller must free the returned table. */
242 silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname,
243 char *server, unsigned int *clients_count)
245 SilcIDCacheList list = NULL;
246 SilcIDCacheEntry id_cache = NULL;
247 SilcClientEntry *clients;
250 if (!silc_idcache_find_by_data(id_list->clients, nickname, &list))
253 clients = silc_calloc(silc_idcache_list_count(list), sizeof(*clients));
256 silc_idcache_list_first(list, &id_cache);
257 clients[i++] = (SilcClientEntry)id_cache->context;
259 while (silc_idcache_list_next(list, &id_cache))
260 clients[i++] = (SilcClientEntry)id_cache->context;
262 silc_idcache_list_free(list);
270 /* Returns all clients matching requested nickname. Number of clients is
271 returned to `clients_count'. Caller must free the returned table. */
274 silc_idlist_get_clients_by_hash(SilcIDList id_list, char *nickname,
276 unsigned int *clients_count)
278 SilcIDCacheList list = NULL;
279 SilcIDCacheEntry id_cache = NULL;
280 SilcClientEntry *clients;
281 unsigned char hash[32];
284 silc_hash_make(md5hash, nickname, strlen(nickname), hash);
286 if (!silc_idcache_find_by_data(id_list->clients, hash, &list))
289 clients = silc_calloc(silc_idcache_list_count(list), sizeof(*clients));
292 silc_idcache_list_first(list, &id_cache);
293 clients[i++] = (SilcClientEntry)id_cache->context;
295 while (silc_idcache_list_next(list, &id_cache))
296 clients[i++] = (SilcClientEntry)id_cache->context;
298 silc_idcache_list_free(list);
306 /* Finds client entry by nickname. */
309 silc_idlist_find_client_by_nickname(SilcIDList id_list, char *nickname,
310 char *server, SilcIDCacheEntry *ret_entry)
312 SilcIDCacheList list = NULL;
313 SilcIDCacheEntry id_cache = NULL;
314 SilcClientEntry client = NULL;
316 SILC_LOG_DEBUG(("Finding client by nickname"));
319 if (!silc_idcache_find_by_data(id_list->clients, nickname, &list))
323 while (silc_idcache_list_next(list, &id_cache)) {
324 client = (SilcClientEntry)id_cache->context;
326 if (!strcmp(server, XXX, strlen(server)))
333 silc_idcache_list_free(list);
338 if (!silc_idcache_find_by_data_one(id_list->clients, nickname, &id_cache))
341 client = (SilcClientEntry)id_cache->context;
344 *ret_entry = id_cache;
350 /* Finds client by nickname hash. */
353 silc_idlist_find_client_by_hash(SilcIDList id_list, char *nickname,
354 SilcHash md5hash, SilcIDCacheEntry *ret_entry)
356 SilcIDCacheList list = NULL;
357 SilcIDCacheEntry id_cache = NULL;
358 SilcClientEntry client = NULL;
359 unsigned char hash[32];
361 SILC_LOG_DEBUG(("Finding client by hash"));
363 silc_hash_make(md5hash, nickname, strlen(nickname), hash);
365 if (!silc_idcache_find_by_id(id_list->clients, SILC_ID_CACHE_ANY,
366 SILC_ID_CLIENT, &list))
369 if (!silc_idcache_list_first(list, &id_cache)) {
370 silc_idcache_list_free(list);
375 client = (SilcClientEntry)id_cache->context;
377 if (client && !SILC_ID_COMPARE_HASH(client->id, hash))
383 if (!silc_idcache_list_next(list, &id_cache))
387 silc_idcache_list_free(list);
390 *ret_entry = id_cache;
395 /* Finds client by Client ID */
398 silc_idlist_find_client_by_id(SilcIDList id_list, SilcClientID *id,
399 SilcIDCacheEntry *ret_entry)
401 SilcIDCacheEntry id_cache = NULL;
402 SilcClientEntry client;
407 SILC_LOG_DEBUG(("Finding client by ID"));
409 if (!silc_idcache_find_by_id_one(id_list->clients, (void *)id,
410 SILC_ID_CLIENT, &id_cache))
413 client = (SilcClientEntry)id_cache->context;
416 *ret_entry = id_cache;
421 /* Replaces old Client ID with new one */
424 silc_idlist_replace_client_id(SilcIDList id_list, SilcClientID *old_id,
425 SilcClientID *new_id)
427 SilcIDCacheEntry id_cache = NULL;
428 SilcClientEntry client;
430 if (!old_id || !new_id)
433 SILC_LOG_DEBUG(("Replacing Client ID"));
435 if (!silc_idcache_find_by_id_one(id_list->clients, (void *)old_id,
436 SILC_ID_CLIENT, &id_cache))
439 client = (SilcClientEntry)id_cache->context;
440 silc_free(client->id);
442 id_cache->id = (void *)new_id;
444 /* If the old ID Cache data was the hash value of the old Client ID
445 replace it with the hash of new Client ID */
446 if (id_cache->data && !SILC_ID_COMPARE_HASH(old_id, id_cache->data)) {
447 silc_free(id_cache->data);
448 id_cache->data = silc_calloc(sizeof(new_id->hash), sizeof(unsigned char));
449 memcpy(id_cache->data, new_id->hash, sizeof(new_id->hash));
450 silc_idcache_sort_by_data(id_list->clients);
457 /******************************************************************************
459 Channel entry functions
461 ******************************************************************************/
463 /* Add new channel entry. This add the new channel entry to the ID cache
464 system and returns the allocated entry or NULL on error. */
467 silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode,
468 SilcChannelID *id, SilcServerEntry router,
469 SilcCipher channel_key)
471 SilcChannelEntry channel;
473 channel = silc_calloc(1, sizeof(*channel));
474 channel->channel_name = channel_name;
475 channel->mode = mode;
477 channel->router = router;
478 channel->channel_key = channel_key;
479 silc_list_init(channel->user_list, struct SilcChannelClientEntryStruct,
482 if (!silc_idcache_add(id_list->channels, channel->channel_name,
483 SILC_ID_CHANNEL, (void *)channel->id,
484 (void *)channel, TRUE)) {
492 /* Free channel entry. This free's everything. */
494 void silc_idlist_del_channel(SilcIDList id_list, SilcChannelEntry entry)
497 SilcChannelClientEntry chl;
499 /* Remove from cache */
501 silc_idcache_del_by_id(id_list->channels, SILC_ID_CHANNEL,
505 if (entry->channel_name)
506 silc_free(entry->channel_name);
508 silc_free(entry->id);
510 silc_free(entry->topic);
511 if (entry->channel_key)
512 silc_cipher_free(entry->channel_key);
514 memset(entry->key, 0, entry->key_len / 8);
515 silc_free(entry->key);
517 memset(entry->iv, 0, sizeof(entry->iv));
519 silc_list_start(entry->user_list);
520 while ((chl = silc_list_get(entry->user_list)) != SILC_LIST_END) {
521 silc_list_del(entry->user_list, chl);
527 /* Finds channel by channel name. Channel names are unique and they
528 are not case-sensitive. */
531 silc_idlist_find_channel_by_name(SilcIDList id_list, char *name,
532 SilcIDCacheEntry *ret_entry)
534 SilcIDCacheList list = NULL;
535 SilcIDCacheEntry id_cache = NULL;
536 SilcChannelEntry channel;
538 SILC_LOG_DEBUG(("Finding channel by name"));
540 if (!silc_idcache_find_by_data_loose(id_list->channels, name, &list))
543 if (!silc_idcache_list_first(list, &id_cache)) {
544 silc_idcache_list_free(list);
548 channel = (SilcChannelEntry)id_cache->context;
551 *ret_entry = id_cache;
553 silc_idcache_list_free(list);
558 /* Finds channel by Channel ID. */
561 silc_idlist_find_channel_by_id(SilcIDList id_list, SilcChannelID *id,
562 SilcIDCacheEntry *ret_entry)
564 SilcIDCacheEntry id_cache = NULL;
565 SilcChannelEntry channel;
570 SILC_LOG_DEBUG(("Finding channel by ID"));
572 if (!silc_idcache_find_by_id_one(id_list->channels, (void *)id,
573 SILC_ID_CHANNEL, &id_cache))
576 channel = (SilcChannelEntry)id_cache->context;
579 *ret_entry = id_cache;