5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2001 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(("Server ID (%s)",
120 silc_id_render(id, SILC_ID_SERVER)));
122 if (!silc_idcache_find_by_id_one(id_list->servers, (void *)id,
123 SILC_ID_SERVER, &id_cache))
126 server = (SilcServerEntry)id_cache->context;
129 *ret_entry = id_cache;
134 /* Replaces old Server ID with new one */
137 silc_idlist_replace_server_id(SilcIDList id_list, SilcServerID *old_id,
138 SilcServerID *new_id)
140 SilcIDCacheEntry id_cache = NULL;
141 SilcServerEntry server;
143 if (!old_id || !new_id)
146 SILC_LOG_DEBUG(("Replacing Server ID"));
148 if (!silc_idcache_find_by_id_one(id_list->servers, (void *)old_id,
149 SILC_ID_SERVER, &id_cache))
152 server = (SilcServerEntry)id_cache->context;
153 silc_free(server->id);
155 id_cache->id = (void *)new_id;
160 /* Removes and free's server entry from ID list */
162 void silc_idlist_del_server(SilcIDList id_list, SilcServerEntry entry)
165 /* Remove from cache */
167 silc_idcache_del_by_id(id_list->servers, SILC_ID_SERVER,
171 if (entry->server_name)
172 silc_free(entry->server_name);
174 silc_free(entry->id);
176 memset(entry, 'F', sizeof(*entry));
181 /******************************************************************************
183 Client entry functions
185 ******************************************************************************/
187 /* Add new client entry. This adds the client entry to ID cache system
188 and returns the allocated client entry or NULL on error. This is
189 called when new client connection is accepted to the server. If The
190 `router' is provided then the all server routines assume that the client
191 is not directly connected local client but it has router set and is
192 remote. If this is the case then `connection' must be NULL. If, on the
193 other hand, the `connection' is provided then the client is assumed
194 to be directly connected local client and `router' must be NULL. */
197 silc_idlist_add_client(SilcIDList id_list, unsigned char *nickname,
198 char *username, char *userinfo, SilcClientID *id,
199 SilcServerEntry router, void *connection)
201 SilcClientEntry client;
203 SILC_LOG_DEBUG(("Adding new client entry"));
205 client = silc_calloc(1, sizeof(*client));
206 client->nickname = nickname;
207 client->username = username;
208 client->userinfo = userinfo;
210 client->router = router;
211 client->connection = connection;
212 silc_list_init(client->channels, struct SilcChannelClientEntryStruct,
215 if (!silc_idcache_add(id_list->clients, nickname, SILC_ID_CLIENT,
216 (void *)client->id, (void *)client, TRUE)) {
224 /* Free client entry. This free's everything and removes the entry
225 from ID cache. Call silc_idlist_del_data before calling this one. */
227 void silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry)
230 /* Remove from cache */
232 silc_idcache_del_by_id(id_list->clients, SILC_ID_CLIENT,
237 silc_free(entry->nickname);
239 silc_free(entry->username);
241 silc_free(entry->userinfo);
243 silc_free(entry->id);
245 memset(entry, 'F', sizeof(*entry));
250 /* Returns all clients matching requested nickname. Number of clients is
251 returned to `clients_count'. Caller must free the returned table. */
254 silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname,
255 char *server, unsigned int *clients_count)
257 SilcIDCacheList list = NULL;
258 SilcIDCacheEntry id_cache = NULL;
259 SilcClientEntry *clients;
262 if (!silc_idcache_find_by_data(id_list->clients, nickname, &list))
265 clients = silc_calloc(silc_idcache_list_count(list), sizeof(*clients));
268 silc_idcache_list_first(list, &id_cache);
269 clients[i++] = (SilcClientEntry)id_cache->context;
271 while (silc_idcache_list_next(list, &id_cache))
272 clients[i++] = (SilcClientEntry)id_cache->context;
274 silc_idcache_list_free(list);
282 /* Returns all clients matching requested nickname. Number of clients is
283 returned to `clients_count'. Caller must free the returned table. */
286 silc_idlist_get_clients_by_hash(SilcIDList id_list, char *nickname,
288 unsigned int *clients_count)
290 SilcIDCacheList list = NULL;
291 SilcIDCacheEntry id_cache = NULL;
292 SilcClientEntry *clients;
293 unsigned char hash[32];
296 silc_hash_make(md5hash, nickname, strlen(nickname), hash);
298 if (!silc_idcache_find_by_data(id_list->clients, hash, &list))
301 clients = silc_calloc(silc_idcache_list_count(list), sizeof(*clients));
304 silc_idcache_list_first(list, &id_cache);
305 clients[i++] = (SilcClientEntry)id_cache->context;
307 while (silc_idcache_list_next(list, &id_cache))
308 clients[i++] = (SilcClientEntry)id_cache->context;
310 silc_idcache_list_free(list);
318 /* Finds client entry by nickname. */
321 silc_idlist_find_client_by_nickname(SilcIDList id_list, char *nickname,
322 char *server, SilcIDCacheEntry *ret_entry)
324 SilcIDCacheList list = NULL;
325 SilcIDCacheEntry id_cache = NULL;
326 SilcClientEntry client = NULL;
328 SILC_LOG_DEBUG(("Client by nickname"));
331 if (!silc_idcache_find_by_data(id_list->clients, nickname, &list))
335 while (silc_idcache_list_next(list, &id_cache)) {
336 client = (SilcClientEntry)id_cache->context;
338 if (!strcmp(server, XXX, strlen(server)))
345 silc_idcache_list_free(list);
350 if (!silc_idcache_find_by_data_one(id_list->clients, nickname, &id_cache))
353 client = (SilcClientEntry)id_cache->context;
356 *ret_entry = id_cache;
359 SILC_LOG_DEBUG(("Found"));
364 /* Finds client by nickname hash. */
367 silc_idlist_find_client_by_hash(SilcIDList id_list, char *nickname,
368 SilcHash md5hash, SilcIDCacheEntry *ret_entry)
370 SilcIDCacheList list = NULL;
371 SilcIDCacheEntry id_cache = NULL;
372 SilcClientEntry client = NULL;
373 unsigned char hash[32];
375 SILC_LOG_DEBUG(("Client by hash"));
377 silc_hash_make(md5hash, nickname, strlen(nickname), hash);
379 if (!silc_idcache_find_by_id(id_list->clients, SILC_ID_CACHE_ANY,
380 SILC_ID_CLIENT, &list))
383 if (!silc_idcache_list_first(list, &id_cache)) {
384 silc_idcache_list_free(list);
389 client = (SilcClientEntry)id_cache->context;
391 if (client && !SILC_ID_COMPARE_HASH(client->id, hash))
397 if (!silc_idcache_list_next(list, &id_cache))
401 silc_idcache_list_free(list);
404 *ret_entry = id_cache;
406 SILC_LOG_DEBUG(("Found"));
411 /* Finds client by Client ID */
414 silc_idlist_find_client_by_id(SilcIDList id_list, SilcClientID *id,
415 SilcIDCacheEntry *ret_entry)
417 SilcIDCacheEntry id_cache = NULL;
418 SilcClientEntry client;
423 SILC_LOG_DEBUG(("Client ID (%s)",
424 silc_id_render(id, SILC_ID_CLIENT)));
426 if (!silc_idcache_find_by_id_one(id_list->clients, (void *)id,
427 SILC_ID_CLIENT, &id_cache))
430 client = (SilcClientEntry)id_cache->context;
433 *ret_entry = id_cache;
435 SILC_LOG_DEBUG(("Found"));
440 /* Replaces old Client ID with new one */
443 silc_idlist_replace_client_id(SilcIDList id_list, SilcClientID *old_id,
444 SilcClientID *new_id)
446 SilcIDCacheEntry id_cache = NULL;
447 SilcClientEntry client;
449 if (!old_id || !new_id)
452 SILC_LOG_DEBUG(("Replacing Client ID"));
454 if (!silc_idcache_find_by_id_one(id_list->clients, (void *)old_id,
455 SILC_ID_CLIENT, &id_cache))
458 client = (SilcClientEntry)id_cache->context;
459 silc_free(client->id);
461 id_cache->id = (void *)new_id;
463 /* If the old ID Cache data was the hash value of the old Client ID
464 replace it with the hash of new Client ID */
465 if (id_cache->data && !SILC_ID_COMPARE_HASH(old_id, id_cache->data)) {
466 silc_free(id_cache->data);
467 id_cache->data = silc_calloc(sizeof(new_id->hash), sizeof(unsigned char));
468 memcpy(id_cache->data, new_id->hash, sizeof(new_id->hash));
469 silc_idcache_sort_by_data(id_list->clients);
476 /******************************************************************************
478 Channel entry functions
480 ******************************************************************************/
482 /* Add new channel entry. This add the new channel entry to the ID cache
483 system and returns the allocated entry or NULL on error. */
486 silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode,
487 SilcChannelID *id, SilcServerEntry router,
488 SilcCipher channel_key)
490 SilcChannelEntry channel;
492 channel = silc_calloc(1, sizeof(*channel));
493 channel->channel_name = channel_name;
494 channel->mode = mode;
496 channel->router = router;
497 channel->channel_key = channel_key;
498 silc_list_init(channel->user_list, struct SilcChannelClientEntryStruct,
501 if (!silc_idcache_add(id_list->channels, channel->channel_name,
502 SILC_ID_CHANNEL, (void *)channel->id,
503 (void *)channel, TRUE)) {
511 /* Free channel entry. This free's everything. */
513 int silc_idlist_del_channel(SilcIDList id_list, SilcChannelEntry entry)
516 SilcChannelClientEntry chl;
518 /* Remove from cache */
520 if (!silc_idcache_del_by_id(id_list->channels, SILC_ID_CHANNEL,
525 if (entry->channel_name)
526 silc_free(entry->channel_name);
528 silc_free(entry->id);
530 silc_free(entry->topic);
531 if (entry->channel_key)
532 silc_cipher_free(entry->channel_key);
534 memset(entry->key, 0, entry->key_len / 8);
535 silc_free(entry->key);
538 silc_list_start(entry->user_list);
539 while ((chl = silc_list_get(entry->user_list)) != SILC_LIST_END) {
540 silc_list_del(entry->user_list, chl);
544 memset(entry, 'F', sizeof(*entry));
552 /* Finds channel by channel name. Channel names are unique and they
553 are not case-sensitive. */
556 silc_idlist_find_channel_by_name(SilcIDList id_list, char *name,
557 SilcIDCacheEntry *ret_entry)
559 SilcIDCacheList list = NULL;
560 SilcIDCacheEntry id_cache = NULL;
561 SilcChannelEntry channel;
563 SILC_LOG_DEBUG(("Channel by name"));
565 if (!silc_idcache_find_by_data_loose(id_list->channels, name, &list))
568 if (!silc_idcache_list_first(list, &id_cache)) {
569 silc_idcache_list_free(list);
573 channel = (SilcChannelEntry)id_cache->context;
576 *ret_entry = id_cache;
578 silc_idcache_list_free(list);
580 SILC_LOG_DEBUG(("Found"));
585 /* Finds channel by Channel ID. */
588 silc_idlist_find_channel_by_id(SilcIDList id_list, SilcChannelID *id,
589 SilcIDCacheEntry *ret_entry)
591 SilcIDCacheEntry id_cache = NULL;
592 SilcChannelEntry channel;
597 SILC_LOG_DEBUG(("Channel ID (%s)",
598 silc_id_render(id, SILC_ID_CHANNEL)));
600 if (!silc_idcache_find_by_id_one(id_list->channels, (void *)id,
601 SILC_ID_CHANNEL, &id_cache))
604 channel = (SilcChannelEntry)id_cache->context;
607 *ret_entry = id_cache;
609 SILC_LOG_DEBUG(("Found"));
614 /* Replaces old Channel ID with new one. This is done when router forces
615 normal server to change Channel ID. */
618 silc_idlist_replace_channel_id(SilcIDList id_list, SilcChannelID *old_id,
619 SilcChannelID *new_id)
621 SilcIDCacheEntry id_cache = NULL;
622 SilcChannelEntry channel;
624 if (!old_id || !new_id)
627 SILC_LOG_DEBUG(("Replacing Channel ID"));
629 if (!silc_idcache_find_by_id_one(id_list->channels, (void *)old_id,
630 SILC_ID_CHANNEL, &id_cache))
633 channel = (SilcChannelEntry)id_cache->context;
634 silc_free(channel->id);
635 channel->id = new_id;
636 id_cache->id = (void *)new_id;