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