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