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;
347 SILC_LOG_DEBUG(("Found"));
352 /* Finds client by nickname hash. */
355 silc_idlist_find_client_by_hash(SilcIDList id_list, char *nickname,
356 SilcHash md5hash, SilcIDCacheEntry *ret_entry)
358 SilcIDCacheList list = NULL;
359 SilcIDCacheEntry id_cache = NULL;
360 SilcClientEntry client = NULL;
361 unsigned char hash[32];
363 SILC_LOG_DEBUG(("Finding client by hash"));
365 silc_hash_make(md5hash, nickname, strlen(nickname), hash);
367 if (!silc_idcache_find_by_id(id_list->clients, SILC_ID_CACHE_ANY,
368 SILC_ID_CLIENT, &list))
371 if (!silc_idcache_list_first(list, &id_cache)) {
372 silc_idcache_list_free(list);
377 client = (SilcClientEntry)id_cache->context;
379 if (client && !SILC_ID_COMPARE_HASH(client->id, hash))
385 if (!silc_idcache_list_next(list, &id_cache))
389 silc_idcache_list_free(list);
392 *ret_entry = id_cache;
394 SILC_LOG_DEBUG(("Found"));
399 /* Finds client by Client ID */
402 silc_idlist_find_client_by_id(SilcIDList id_list, SilcClientID *id,
403 SilcIDCacheEntry *ret_entry)
405 SilcIDCacheEntry id_cache = NULL;
406 SilcClientEntry client;
411 SILC_LOG_DEBUG(("Finding client by ID"));
413 if (!silc_idcache_find_by_id_one(id_list->clients, (void *)id,
414 SILC_ID_CLIENT, &id_cache))
417 client = (SilcClientEntry)id_cache->context;
420 *ret_entry = id_cache;
422 SILC_LOG_DEBUG(("Found"));
427 /* Replaces old Client ID with new one */
430 silc_idlist_replace_client_id(SilcIDList id_list, SilcClientID *old_id,
431 SilcClientID *new_id)
433 SilcIDCacheEntry id_cache = NULL;
434 SilcClientEntry client;
436 if (!old_id || !new_id)
439 SILC_LOG_DEBUG(("Replacing Client ID"));
441 if (!silc_idcache_find_by_id_one(id_list->clients, (void *)old_id,
442 SILC_ID_CLIENT, &id_cache))
445 client = (SilcClientEntry)id_cache->context;
446 silc_free(client->id);
448 id_cache->id = (void *)new_id;
450 /* If the old ID Cache data was the hash value of the old Client ID
451 replace it with the hash of new Client ID */
452 if (id_cache->data && !SILC_ID_COMPARE_HASH(old_id, id_cache->data)) {
453 silc_free(id_cache->data);
454 id_cache->data = silc_calloc(sizeof(new_id->hash), sizeof(unsigned char));
455 memcpy(id_cache->data, new_id->hash, sizeof(new_id->hash));
456 silc_idcache_sort_by_data(id_list->clients);
463 /******************************************************************************
465 Channel entry functions
467 ******************************************************************************/
469 /* Add new channel entry. This add the new channel entry to the ID cache
470 system and returns the allocated entry or NULL on error. */
473 silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode,
474 SilcChannelID *id, SilcServerEntry router,
475 SilcCipher channel_key)
477 SilcChannelEntry channel;
479 channel = silc_calloc(1, sizeof(*channel));
480 channel->channel_name = channel_name;
481 channel->mode = mode;
483 channel->router = router;
484 channel->channel_key = channel_key;
485 silc_list_init(channel->user_list, struct SilcChannelClientEntryStruct,
488 if (!silc_idcache_add(id_list->channels, channel->channel_name,
489 SILC_ID_CHANNEL, (void *)channel->id,
490 (void *)channel, TRUE)) {
498 /* Free channel entry. This free's everything. */
500 void silc_idlist_del_channel(SilcIDList id_list, SilcChannelEntry entry)
503 SilcChannelClientEntry chl;
505 /* Remove from cache */
507 silc_idcache_del_by_id(id_list->channels, SILC_ID_CHANNEL,
511 if (entry->channel_name)
512 silc_free(entry->channel_name);
514 silc_free(entry->id);
516 silc_free(entry->topic);
517 if (entry->channel_key)
518 silc_cipher_free(entry->channel_key);
520 memset(entry->key, 0, entry->key_len / 8);
521 silc_free(entry->key);
523 memset(entry->iv, 0, sizeof(entry->iv));
525 silc_list_start(entry->user_list);
526 while ((chl = silc_list_get(entry->user_list)) != SILC_LIST_END) {
527 silc_list_del(entry->user_list, chl);
533 /* Finds channel by channel name. Channel names are unique and they
534 are not case-sensitive. */
537 silc_idlist_find_channel_by_name(SilcIDList id_list, char *name,
538 SilcIDCacheEntry *ret_entry)
540 SilcIDCacheList list = NULL;
541 SilcIDCacheEntry id_cache = NULL;
542 SilcChannelEntry channel;
544 SILC_LOG_DEBUG(("Finding channel by name"));
546 if (!silc_idcache_find_by_data_loose(id_list->channels, name, &list))
549 if (!silc_idcache_list_first(list, &id_cache)) {
550 silc_idcache_list_free(list);
554 channel = (SilcChannelEntry)id_cache->context;
557 *ret_entry = id_cache;
559 silc_idcache_list_free(list);
561 SILC_LOG_DEBUG(("Found"));
566 /* Finds channel by Channel ID. */
569 silc_idlist_find_channel_by_id(SilcIDList id_list, SilcChannelID *id,
570 SilcIDCacheEntry *ret_entry)
572 SilcIDCacheEntry id_cache = NULL;
573 SilcChannelEntry channel;
578 SILC_LOG_DEBUG(("Finding channel by ID"));
580 if (!silc_idcache_find_by_id_one(id_list->channels, (void *)id,
581 SILC_ID_CHANNEL, &id_cache))
584 channel = (SilcChannelEntry)id_cache->context;
587 *ret_entry = id_cache;
589 SILC_LOG_DEBUG(("Found"));