Global costemic changes.
[silc.git] / apps / silcd / idlist.c
1 /*
2
3   idlist.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 1997 - 2000 Pekka Riikonen
8
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.
13   
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.
18
19 */
20 /*
21  * $Id$
22  * $Log$
23  * Revision 1.3  2000/07/05 06:14:01  priikone
24  *      Global costemic changes.
25  *
26  * Revision 1.2  2000/07/03 05:52:11  priikone
27  *      Fixed typo and a bug.
28  *
29  * Revision 1.1.1.1  2000/06/27 11:36:56  priikone
30  *      Imported from internal CVS/Added Log headers.
31  *
32  *
33  */
34
35 #include "serverincludes.h"
36 #include "idlist.h"
37
38 /* Adds a new server to the list. The pointer sent as argument is allocated
39    and returned. */
40
41 void silc_idlist_add_server(SilcServerList **list, 
42                             char *server_name, int server_type,
43                             SilcServerID *id, SilcServerList *router,
44                             SilcCipher send_key, SilcCipher receive_key,
45                             SilcPKCS public_key, SilcHmac hmac, 
46                             SilcServerList **new_idlist)
47 {
48   SilcServerList *last, *idlist;
49
50   SILC_LOG_DEBUG(("Adding new server to id list"));
51
52   idlist = silc_calloc(1, sizeof(*idlist));
53   if (idlist == NULL) {
54     SILC_LOG_ERROR(("Could not allocate new server list object"));
55     *new_idlist = NULL;
56     return;
57   }
58
59   /* Set the pointers */
60   idlist->server_name = server_name;
61   idlist->server_type = server_type;
62   idlist->id = id;
63   idlist->router = router;
64   idlist->send_key = send_key;
65   idlist->receive_key = receive_key;
66   idlist->public_key = public_key;
67   idlist->hmac = hmac;
68   idlist->next = idlist;
69   idlist->prev = idlist;
70
71   /* First on the list? */
72   if (!*list) {
73     *list = idlist;
74     *new_idlist = idlist;
75     return;
76   }
77
78   /* Add it to the list */
79   last = (*list)->prev;
80   last->next = idlist;
81   (*list)->prev = idlist;
82   idlist->next = (*list);
83   idlist->prev = last;
84
85   if (new_idlist)
86     *new_idlist = idlist;
87 }
88
89 /* Adds a new client to the client list. This is called when new client 
90    connection is accepted to the server. This adds all the relevant data 
91    about the client and session with it to the list. This list is 
92    referenced for example when sending message to the client. */
93
94 void silc_idlist_add_client(SilcClientList **list, char *nickname,
95                             char *username, char *userinfo,
96                             SilcClientID *id, SilcServerList *router,
97                             SilcCipher send_key, SilcCipher receive_key,
98                             SilcPKCS public_key, SilcHmac hmac, 
99                             SilcClientList **new_idlist)
100 {
101   SilcClientList *last, *idlist;
102
103   SILC_LOG_DEBUG(("Adding new client to id list"));
104
105   idlist = silc_calloc(1, sizeof(*idlist));
106   if (idlist == NULL) {
107     SILC_LOG_ERROR(("Could not allocate new client list object"));
108     return;
109   }
110
111   /* Set the pointers */
112   idlist->nickname = nickname;
113   idlist->username = username;
114   idlist->userinfo = userinfo;
115   idlist->id = id;
116   idlist->router = router;
117   idlist->send_key = send_key;
118   idlist->receive_key = receive_key;
119   idlist->public_key = public_key;
120   idlist->hmac = hmac;
121   idlist->next = idlist;
122   idlist->prev = idlist;
123
124   /* First on the list? */
125   if (!(*list)) {
126     *list = idlist;
127     if (new_idlist)
128       *new_idlist = idlist;
129     return;
130   }
131
132   /* Add it to the list */
133   last = (*list)->prev;
134   last->next = idlist;
135   (*list)->prev = idlist;
136   idlist->next = *list;
137   idlist->prev = last;
138
139   if (new_idlist)
140     *new_idlist = idlist;
141 }
142
143 /* Free client entry.  This free's everything. */
144
145 void silc_idlist_del_client(SilcClientList **list, SilcClientList *entry)
146 {
147   if (entry) {
148     if (entry->nickname)
149       silc_free(entry->nickname);
150     if (entry->username)
151       silc_free(entry->username);
152     if (entry->userinfo)
153       silc_free(entry->userinfo);
154     if (entry->id)
155       silc_free(entry->id);
156     if (entry->send_key)
157       silc_cipher_free(entry->send_key);
158     if (entry->receive_key)
159       silc_cipher_free(entry->receive_key);
160     if (entry->public_key)
161       silc_pkcs_free(entry->public_key);
162     if (entry->hmac)
163       silc_hmac_free(entry->hmac);
164     if (entry->hmac_key) {
165       memset(entry->hmac_key, 0, entry->hmac_key_len);
166       silc_free(entry->hmac_key);
167     }
168
169     /* Last one in list? */
170     if (*list == entry && entry->next == entry) {
171       *list = NULL;
172       silc_free(entry);
173       return;
174     }
175
176     /* At the start of list? */
177     if (*list == entry && entry->next != entry) {
178       *list = entry->next;
179       entry->next->prev = entry->prev;
180       entry->prev->next = *list;
181       silc_free(entry);
182       return;
183     }
184
185     /* Remove from list */
186     entry->prev->next = entry->next;
187     entry->next->prev = entry->prev;
188     silc_free(entry);
189     return;
190   }
191 }
192
193 SilcClientList *
194 silc_idlist_find_client_by_nickname(SilcClientList *list,
195                                     char *nickname,
196                                     char *server)
197 {
198   SilcClientList *first, *entry;
199
200   SILC_LOG_DEBUG(("Finding client by nickname"));
201
202   if (!list)
203     return NULL;
204
205   first = entry = list;
206   if (!strcmp(entry->nickname, nickname)) {
207     SILC_LOG_DEBUG(("Found"));
208     return entry;
209   }
210   entry = entry->next;
211
212   while(entry != first) {
213     if (!strcmp(entry->nickname, nickname)) {
214       SILC_LOG_DEBUG(("Found"));
215       return entry;
216     }
217
218     entry = entry->next;
219   }
220
221   return NULL;
222 }
223
224 SilcClientList *
225 silc_idlist_find_client_by_hash(SilcClientList *list,
226                                 char *nickname, SilcHash md5hash)
227 {
228   SilcClientList *first, *entry;
229   unsigned char hash[16];
230
231   SILC_LOG_DEBUG(("Finding client by nickname hash"));
232
233   if (!list)
234     return NULL;
235
236   /* Make hash of the nickname */
237   silc_hash_make(md5hash, nickname, strlen(nickname), hash);
238
239   first = entry = list;
240   if (entry && !SILC_ID_COMPARE_HASH(entry->id, hash)) {
241     SILC_LOG_DEBUG(("Found"));
242     return entry;
243   }
244   entry = entry->next;
245
246   while(entry != first) {
247     if (entry && !SILC_ID_COMPARE_HASH(entry->id, hash)) {
248       SILC_LOG_DEBUG(("Found"));
249       return entry;
250     }
251
252     entry = entry->next;
253   }
254
255   return NULL;
256 }
257
258 SilcClientList *
259 silc_idlist_find_client_by_id(SilcClientList *list, SilcClientID *id)
260 {
261   SilcClientList *first, *entry;
262
263   SILC_LOG_DEBUG(("Finding client by Client ID"));
264
265   if (!list)
266     return NULL;
267
268   first = entry = list;
269   if (entry && !SILC_ID_CLIENT_COMPARE(entry->id, id)) {
270     SILC_LOG_DEBUG(("Found"));
271     return entry;
272   }
273   entry = entry->next;
274
275   while(entry != first) {
276     if (entry && !SILC_ID_CLIENT_COMPARE(entry->id, id)) {
277       SILC_LOG_DEBUG(("Found"));
278       return entry;
279     }
280
281     entry = entry->next;
282   }
283
284   return NULL;
285 }
286
287 /* Adds new channel to the list. */
288
289 void silc_idlist_add_channel(SilcChannelList **list, 
290                              char *channel_name, int mode,
291                              SilcChannelID *id, SilcServerList *router,
292                              SilcCipher channel_key,
293                              SilcChannelList **new_idlist)
294 {
295   SilcChannelList *last, *idlist;
296
297   SILC_LOG_DEBUG(("Adding new channel to id list"));
298
299   idlist = silc_calloc(1, sizeof(*idlist));
300   if (idlist == NULL) {
301     SILC_LOG_ERROR(("Could not allocate new channel list object"));
302     return;
303   }
304
305   /* Set the pointers */
306   idlist->channel_name = channel_name;
307   idlist->mode = mode;
308   idlist->id = id;
309   idlist->router = router;
310   idlist->channel_key = channel_key;
311   idlist->next = idlist;
312   idlist->prev = idlist;
313
314   /* First on the list? */
315   if (!*list) {
316     *list = idlist;
317     if (new_idlist)
318       *new_idlist = idlist;
319     return;
320   }
321
322   /* Add it to the list */
323   last = (*list)->prev;
324   last->next = idlist;
325   (*list)->prev = idlist;
326   idlist->next = (*list);
327   idlist->prev = last;
328
329   if (new_idlist)
330     *new_idlist = idlist;
331 }
332
333 SilcChannelList *
334 silc_idlist_find_channel_by_id(SilcChannelList *list, SilcChannelID *id)
335 {
336   SilcChannelList *first, *entry;
337
338   SILC_LOG_DEBUG(("Finding channel by Channel ID"));
339
340   if (!list)
341     return NULL;
342
343   first = entry = list;
344   if (entry && !SILC_ID_CHANNEL_COMPARE(entry->id, id)) {
345     SILC_LOG_DEBUG(("Found"));
346     return entry;
347   }
348   entry = entry->next;
349
350   while(entry != first) {
351     if (entry && !SILC_ID_CHANNEL_COMPARE(entry->id, id)) {
352       SILC_LOG_DEBUG(("Found"));
353       return entry;
354     }
355
356     entry = entry->next;
357   }
358
359   return NULL;
360 }
361
362 /* Free channel entry.  This free's everything. */
363
364 void silc_idlist_del_channel(SilcChannelList **list, SilcChannelList *entry)
365 {
366   if (entry) {
367     if (entry->channel_name)
368       silc_free(entry->channel_name);
369     if (entry->id)
370       silc_free(entry->id);
371     if (entry->topic)
372       silc_free(entry->topic);
373     if (entry->channel_key)
374       silc_cipher_free(entry->channel_key);
375     if (entry->key) {
376       memset(entry->key, 0, entry->key_len / 8);
377       silc_free(entry->key);
378     }
379     memset(entry->iv, 0, sizeof(entry->iv));
380
381     if (entry->user_list_count)
382       silc_free(entry->user_list);
383
384     /* Last one in list? */
385     if (*list == entry && entry->next == entry) {
386       *list = NULL;
387       silc_free(entry);
388       return;
389     }
390
391     /* At the start of list? */
392     if (*list == entry && entry->next != entry) {
393       *list = entry->next;
394       entry->next->prev = entry->prev;
395       entry->prev->next = *list;
396       silc_free(entry);
397       return;
398     }
399
400     /* Remove from list */
401     entry->prev->next = entry->next;
402     entry->next->prev = entry->prev;
403     silc_free(entry);
404     return;
405   }
406 }