Watcher list support added.
[silc.git] / apps / silcd / server_util.c
1 /*
2
3   server_util.c 
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2002 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; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19 /* $Id$ */
20
21 #include "serverincludes.h"
22 #include "server_internal.h"
23
24 extern char *server_version;
25
26 /* Removes the client from channels and possibly removes the channels
27    as well.  After removing those channels that exist, their channel
28    keys are regnerated. This is called only by the function
29    silc_server_remove_clients_by_server. */
30
31 static void silc_server_remove_clients_channels(SilcServer server, 
32                                                 SilcSocketConnection sock,
33                                                 SilcClientEntry client,
34                                                 SilcHashTable channels)
35 {
36   SilcChannelEntry channel;
37   SilcChannelClientEntry chl;
38   SilcHashTableList htl;
39   SilcBuffer clidp;
40
41   SILC_LOG_DEBUG(("Start"));
42
43   if (!client || !client->id)
44     return;
45
46   clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
47
48   /* Remove the client from all channels. The client is removed from
49      the channels' user list. */
50   silc_hash_table_list(client->channels, &htl);
51   while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
52     channel = chl->channel;
53
54     /* Remove channel from client's channel list */
55     silc_hash_table_del(client->channels, channel);
56
57     /* Remove channel if there is no users anymore */
58     if (server->server_type == SILC_ROUTER &&
59         silc_hash_table_count(channel->user_list) < 2) {
60
61       if (silc_hash_table_find(channels, channel, NULL, NULL))
62         silc_hash_table_del(channels, channel);
63
64       if (channel->rekey)
65         silc_schedule_task_del_by_context(server->schedule, channel->rekey);
66
67       if (silc_idlist_del_channel(server->local_list, channel))
68         server->stat.my_channels--;
69       else 
70         silc_idlist_del_channel(server->global_list, channel);
71       continue;
72     }
73
74     /* Remove client from channel's client list */
75     silc_hash_table_del(channel->user_list, chl->client);
76     channel->user_count--;
77
78     /* If there is no global users on the channel anymore mark the channel
79        as local channel. Do not check if the removed client is local client. */
80     if (server->server_type != SILC_ROUTER && channel->global_users && 
81         chl->client->router && !silc_server_channel_has_global(channel))
82       channel->global_users = FALSE;
83
84     silc_free(chl);
85     server->stat.my_chanclients--;
86
87     /* If there is not at least one local user on the channel then we don't
88        need the channel entry anymore, we can remove it safely. */
89     if (server->server_type != SILC_ROUTER &&
90         !silc_server_channel_has_local(channel)) {
91
92       if (silc_hash_table_find(channels, channel, NULL, NULL))
93         silc_hash_table_del(channels, channel);
94
95       if (channel->rekey)
96         silc_schedule_task_del_by_context(server->schedule, channel->rekey);
97
98       if (channel->founder_key) {
99         /* The founder auth data exists, do not remove the channel entry */
100         SilcChannelClientEntry chl2;
101         SilcHashTableList htl2;
102
103         channel->disabled = TRUE;
104
105         silc_hash_table_list(channel->user_list, &htl2);
106         while (silc_hash_table_get(&htl2, NULL, (void **)&chl2)) {
107           silc_hash_table_del(chl2->client->channels, channel);
108           silc_hash_table_del(channel->user_list, chl2->client);
109           channel->user_count--;
110           silc_free(chl2);
111         }
112         silc_hash_table_list_reset(&htl2);
113         continue;
114       }
115
116       /* Remove the channel entry */
117       if (silc_idlist_del_channel(server->local_list, channel))
118         server->stat.my_channels--;
119       else 
120         silc_idlist_del_channel(server->global_list, channel);
121       continue;
122     }
123
124     /* Add the channel to the the channels list to regenerate the 
125        channel key */
126     if (!silc_hash_table_find(channels, channel, NULL, NULL))
127       silc_hash_table_add(channels, channel, channel);
128   }
129   silc_hash_table_list_reset(&htl);
130
131   silc_buffer_free(clidp);
132 }
133
134 /* This function is used to remove all client entries by the server `entry'.
135    This is called when the connection is lost to the server. In this case
136    we must invalidate all the client entries owned by the server `entry'. 
137    If the `server_signoff' is TRUE then the SERVER_SIGNOFF notify is
138    distributed to our local clients. */
139
140 bool silc_server_remove_clients_by_server(SilcServer server, 
141                                           SilcServerEntry entry,
142                                           bool server_signoff)
143 {
144   SilcIDCacheList list = NULL;
145   SilcIDCacheEntry id_cache = NULL;
146   SilcClientEntry client = NULL;
147   SilcBuffer idp;
148   SilcClientEntry *clients = NULL;
149   SilcUInt32 clients_c = 0;
150   unsigned char **argv = NULL;
151   SilcUInt32 *argv_lens = NULL, *argv_types = NULL, argc = 0;
152   SilcHashTableList htl;
153   SilcChannelEntry channel;
154   SilcHashTable channels;
155   int i;
156
157   SILC_LOG_DEBUG(("Start"));
158
159   /* Allocate the hash table that holds the channels that require
160      channel key re-generation after we've removed this server's clients
161      from the channels. */
162   channels = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL,
163                                    NULL, NULL, TRUE);
164
165   if (server_signoff) {
166     idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
167     argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
168     argv_lens = silc_realloc(argv_lens,  sizeof(*argv_lens) * (argc + 1));
169     argv_types = silc_realloc(argv_types, sizeof(*argv_types) * (argc + 1));
170     argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
171     memcpy(argv[argc], idp->data, idp->len);
172     argv_lens[argc] = idp->len;
173     argv_types[argc] = argc + 1;
174     argc++;
175     silc_buffer_free(idp);
176   }
177
178   if (silc_idcache_get_all(server->local_list->clients, &list)) {
179
180     if (silc_idcache_list_first(list, &id_cache)) {
181       while (id_cache) {
182         client = (SilcClientEntry)id_cache->context;
183         if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
184           if (!silc_idcache_list_next(list, &id_cache))
185             break;
186           else
187             continue;
188         }
189
190         if (client->router != entry) {
191           if (server_signoff) {
192             clients = silc_realloc(clients, 
193                                    sizeof(*clients) * (clients_c + 1));
194             clients[clients_c] = client;
195             clients_c++;
196           }
197
198           if (!silc_idcache_list_next(list, &id_cache))
199             break;
200           else
201             continue;
202         }
203
204         if (server_signoff) {
205           idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
206           argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
207           argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
208                                    (argc + 1));
209           argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
210                                     (argc + 1));
211           argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
212           memcpy(argv[argc], idp->data, idp->len);
213           argv_lens[argc] = idp->len;
214           argv_types[argc] = argc + 1;
215           argc++;
216           silc_buffer_free(idp);
217         }
218
219         /* Update statistics */
220         server->stat.clients--;
221         if (server->stat.cell_clients)
222           server->stat.cell_clients--;
223         SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
224         SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
225
226         /* Remove the client entry */
227         silc_server_remove_clients_channels(server, NULL, client, channels);
228         if (!server_signoff) {
229           client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
230           id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
231         } else {
232           silc_idlist_del_client(server->local_list, client);
233
234           /* Remove this client from watcher list if it is */
235           silc_server_del_from_watcher_list(server, client);
236         }
237
238         if (!silc_idcache_list_next(list, &id_cache))
239           break;
240       }
241     }
242     silc_idcache_list_free(list);
243   }
244   
245   if (silc_idcache_get_all(server->global_list->clients, &list)) {
246
247     if (silc_idcache_list_first(list, &id_cache)) {
248       while (id_cache) {
249         client = (SilcClientEntry)id_cache->context;
250         if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
251           if (!silc_idcache_list_next(list, &id_cache))
252             break;
253           else
254             continue;
255         }
256         
257         if (client->router != entry) {
258           if (server_signoff && client->connection) {
259             clients = silc_realloc(clients, 
260                                    sizeof(*clients) * (clients_c + 1));
261             clients[clients_c] = client;
262             clients_c++;
263           }
264
265           if (!silc_idcache_list_next(list, &id_cache))
266             break;
267           else
268             continue;
269         }
270
271         if (server_signoff) {
272           idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
273           argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
274           argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
275                                    (argc + 1));
276           argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
277                                     (argc + 1));
278           argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
279           memcpy(argv[argc], idp->data, idp->len);
280           argv_lens[argc] = idp->len;
281           argv_types[argc] = argc + 1;
282           argc++;
283           silc_buffer_free(idp);
284         }
285
286         /* Update statistics */
287         server->stat.clients--;
288         if (server->stat.cell_clients)
289           server->stat.cell_clients--;
290         SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
291         SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
292
293         /* Remove the client entry */
294         silc_server_remove_clients_channels(server, NULL, client, channels);
295         if (!server_signoff) {
296           client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
297           id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
298         } else {
299           silc_idlist_del_client(server->global_list, client);
300         }
301
302         if (!silc_idcache_list_next(list, &id_cache))
303           break;
304       }
305     }
306     silc_idcache_list_free(list);
307   }
308
309   /* Send the SERVER_SIGNOFF notify */
310   if (server_signoff) {
311     SilcBuffer args, not;
312
313     /* Send SERVER_SIGNOFF notify to our primary router */
314     if (!server->standalone && server->router &&
315         server->router != entry) {
316       args = silc_argument_payload_encode(1, argv, argv_lens,
317                                           argv_types);
318       silc_server_send_notify_args(server, 
319                                    server->router->connection,
320                                    server->server_type == SILC_SERVER ? 
321                                    FALSE : TRUE, 
322                                    SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
323                                    argc, args);
324       silc_buffer_free(args);
325     }
326
327     /* Send to local clients. We also send the list of client ID's that
328        is to be removed for those servers that would like to use that list. */
329     args = silc_argument_payload_encode(argc, argv, argv_lens,
330                                         argv_types);
331     not = silc_notify_payload_encode_args(SILC_NOTIFY_TYPE_SERVER_SIGNOFF, 
332                                           argc, args);
333     silc_server_packet_send_clients(server, clients, clients_c,
334                                     SILC_PACKET_NOTIFY, 0, FALSE,
335                                     not->data, not->len, FALSE);
336
337     silc_free(clients);
338     silc_buffer_free(args);
339     silc_buffer_free(not);
340     for (i = 0; i < argc; i++)
341       silc_free(argv[i]);
342     silc_free(argv);
343     silc_free(argv_lens);
344     silc_free(argv_types);
345   }
346
347   /* We must now re-generate the channel key for all channels that had
348      this server's client(s) on the channel. As they left the channel we
349      must re-generate the channel key. */
350   silc_hash_table_list(channels, &htl);
351   while (silc_hash_table_get(&htl, NULL, (void **)&channel)) {
352     if (!silc_server_create_channel_key(server, channel, 0)) {
353       silc_hash_table_list_reset(&htl);
354       silc_hash_table_free(channels);
355       return FALSE;
356     }
357
358     /* Do not send the channel key if private channel key mode is set */
359     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY)
360       continue;
361
362     silc_server_send_channel_key(server, NULL, channel, 
363                                  server->server_type == SILC_ROUTER ? 
364                                  FALSE : !server->standalone);
365   }
366   silc_hash_table_list_reset(&htl);
367   silc_hash_table_free(channels);
368
369   return TRUE;
370 }
371
372 static SilcServerEntry
373 silc_server_update_clients_by_real_server(SilcServer server,
374                                           SilcServerEntry from,
375                                           SilcClientEntry client,
376                                           bool local,
377                                           SilcIDCacheEntry client_cache)
378 {
379   SilcServerEntry server_entry;
380   SilcIDCacheEntry id_cache = NULL;
381   SilcIDCacheList list;
382
383   if (!silc_idcache_get_all(server->local_list->servers, &list))
384     return NULL;
385
386   if (silc_idcache_list_first(list, &id_cache)) {
387     while (id_cache) {
388       server_entry = (SilcServerEntry)id_cache->context;
389       if (server_entry != from &&
390           SILC_ID_COMPARE(server_entry->id, client->id, 
391                           client->id->ip.data_len)) {
392         SILC_LOG_DEBUG(("Found (local) %s",
393                         silc_id_render(server_entry->id, SILC_ID_SERVER)));
394
395         if (!server_entry->data.send_key && server_entry->router) {
396           SILC_LOG_DEBUG(("Server not locally connected, use its router"));
397           /* If the client is not marked as local then move it to local list
398              since the server is local. */
399           if (!local) {
400             SILC_LOG_DEBUG(("Moving client to local list"));
401             silc_idcache_add(server->local_list->clients, client_cache->name,
402                              client_cache->id, client_cache->context,
403                              client_cache->expire, NULL);
404             silc_idcache_del_by_context(server->global_list->clients, client);
405           }
406           server_entry = server_entry->router;
407         } else {
408           /* If the client is not marked as local then move it to local list
409              since the server is local. */
410           if (server_entry->server_type != SILC_BACKUP_ROUTER && !local) {
411             SILC_LOG_DEBUG(("Moving client to local list"));
412             silc_idcache_add(server->local_list->clients, client_cache->name,
413                              client_cache->id, client_cache->context,
414                              client_cache->expire, NULL);
415             silc_idcache_del_by_context(server->global_list->clients, client);
416           }
417         }
418
419         silc_idcache_list_free(list);
420         return server_entry;
421       }
422
423       if (!silc_idcache_list_next(list, &id_cache))
424         break;
425     }
426   }
427
428   silc_idcache_list_free(list);
429
430   if (!silc_idcache_get_all(server->global_list->servers, &list))
431     return NULL;
432
433   if (silc_idcache_list_first(list, &id_cache)) {
434     while (id_cache) {
435       server_entry = (SilcServerEntry)id_cache->context;
436       if (server_entry != from &&
437           SILC_ID_COMPARE(server_entry->id, client->id, 
438                           client->id->ip.data_len)) {
439         SILC_LOG_DEBUG(("Found (global) %s",
440                         silc_id_render(server_entry->id, SILC_ID_SERVER)));
441
442         if (!server_entry->data.send_key && server_entry->router) {
443           SILC_LOG_DEBUG(("Server not locally connected, use its router"));
444           /* If the client is marked as local then move it to global list
445              since the server is global. */
446           if (local) {
447             SILC_LOG_DEBUG(("Moving client to global list"));
448             silc_idcache_add(server->global_list->clients, client_cache->name,
449                              client_cache->id, client_cache->context,
450                              client_cache->expire, NULL);
451             silc_idcache_del_by_context(server->local_list->clients, client);
452           }
453           server_entry = server_entry->router;
454         } else {
455           /* If the client is marked as local then move it to global list
456              since the server is global. */
457           if (server_entry->server_type != SILC_BACKUP_ROUTER && local) {
458             SILC_LOG_DEBUG(("Moving client to global list"));
459             silc_idcache_add(server->global_list->clients, client_cache->name,
460                              client_cache->id, client_cache->context,
461                              client_cache->expire, NULL);
462             silc_idcache_del_by_context(server->local_list->clients, client);
463           }
464         }
465
466         silc_idcache_list_free(list);
467         return server_entry;
468       }
469
470       if (!silc_idcache_list_next(list, &id_cache))
471         break;
472     }
473   }
474
475   silc_idcache_list_free(list);
476
477   return NULL;
478 }
479
480 /* Updates the clients that are originated from the `from' to be originated
481    from the `to'. If the `resolve_real_server' is TRUE then this will
482    attempt to figure out which clients really are originated from the
483    `from' and which are originated from a server that we have connection
484    to, when we've acting as backup router. If it is FALSE the `to' will
485    be the new source. This function also removes the clients that are
486    *really* originated from `from' if `remove_from' is TRUE. These are
487    clients that the `from' owns, and not just clients that are behind
488    the `from'. */
489
490 void silc_server_update_clients_by_server(SilcServer server, 
491                                           SilcServerEntry from,
492                                           SilcServerEntry to,
493                                           bool resolve_real_server,
494                                           bool remove_from)
495 {
496   SilcIDCacheList list = NULL;
497   SilcIDCacheEntry id_cache = NULL;
498   SilcClientEntry client = NULL;
499   bool local;
500
501   SILC_LOG_DEBUG(("Start"));
502
503   SILC_LOG_DEBUG(("Updating %s", silc_id_render(from->id,
504                                                 SILC_ID_SERVER)));
505   SILC_LOG_DEBUG(("to %s", silc_id_render(to->id,
506                                           SILC_ID_SERVER)));
507
508
509   local = FALSE;
510   if (silc_idcache_get_all(server->global_list->clients, &list)) {
511     if (silc_idcache_list_first(list, &id_cache)) {
512       while (id_cache) {
513         client = (SilcClientEntry)id_cache->context;
514         if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
515           if (!silc_idcache_list_next(list, &id_cache))
516             break;
517           else
518             continue;
519         }
520
521         SILC_LOG_DEBUG(("Client (global) %s", 
522                         silc_id_render(client->id, SILC_ID_CLIENT)));
523         if (client->router)
524           SILC_LOG_DEBUG(("Client->router (global) %s", 
525                           silc_id_render(client->router->id, SILC_ID_SERVER)));
526
527         if (client->router == from) {
528           /* Skip clients that are *really* owned by the `from' */
529           if (remove_from && SILC_ID_COMPARE(from->id, client->id, 
530                                              client->id->ip.data_len)) {
531             SILC_LOG_DEBUG(("Found really owned client, skip it"));
532             if (!silc_idcache_list_next(list, &id_cache))
533               break;
534             else
535               continue;
536           }
537
538           if (resolve_real_server) {
539             client->router = 
540               silc_server_update_clients_by_real_server(server, from, client,
541                                                         local, id_cache);
542             if (!client->router)
543               client->router = to;
544           } else {
545             client->router = to;
546           }
547         }
548
549         if (!silc_idcache_list_next(list, &id_cache))
550           break;
551       }
552     }
553     silc_idcache_list_free(list);
554   }
555
556   local = TRUE;
557   if (silc_idcache_get_all(server->local_list->clients, &list)) {
558     if (silc_idcache_list_first(list, &id_cache)) {
559       while (id_cache) {
560         client = (SilcClientEntry)id_cache->context;
561         if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
562           if (!silc_idcache_list_next(list, &id_cache))
563             break;
564           else
565             continue;
566         }
567
568         SILC_LOG_DEBUG(("Client (local) %s", 
569                         silc_id_render(client->id, SILC_ID_CLIENT)));
570         if (client->router)
571           SILC_LOG_DEBUG(("Client->router (local) %s", 
572                           silc_id_render(client->router->id, SILC_ID_SERVER)));
573
574         if (client->router == from) {
575           /* Skip clients that are *really* owned by the `from' */
576           if (remove_from && SILC_ID_COMPARE(from->id, client->id, 
577                                              client->id->ip.data_len)) {
578             SILC_LOG_DEBUG(("Found really owned client, skip it"));
579             if (!silc_idcache_list_next(list, &id_cache))
580               break;
581             else
582               continue;
583           }
584
585           if (resolve_real_server) {
586             client->router = 
587               silc_server_update_clients_by_real_server(server, from, client,
588                                                         local, id_cache);
589             if (!client->router)
590               client->router = from; /* on local list put old from */
591           } else {
592             client->router = to;
593           }
594         }
595
596         if (!silc_idcache_list_next(list, &id_cache))
597           break;
598       }
599     }
600     silc_idcache_list_free(list);
601   }
602
603   if (remove_from)
604     /* Now remove the clients that are still marked as orignated from the
605        `from'. These are the clients that really was owned by the `from' and
606        not just exist behind the `from'. */
607     silc_server_remove_clients_by_server(server, from, TRUE);
608 }
609
610 /* Updates servers that are from `from' to be originated from `to'.  This
611    will also update the server's connection to `to's connection. */
612
613 void silc_server_update_servers_by_server(SilcServer server, 
614                                           SilcServerEntry from,
615                                           SilcServerEntry to)
616 {
617   SilcIDCacheList list = NULL;
618   SilcIDCacheEntry id_cache = NULL;
619   SilcServerEntry server_entry = NULL;
620
621   SILC_LOG_DEBUG(("Start"));
622
623   if (silc_idcache_get_all(server->local_list->servers, &list)) {
624     if (silc_idcache_list_first(list, &id_cache)) {
625       while (id_cache) {
626         server_entry = (SilcServerEntry)id_cache->context;
627         if (server_entry->router == from) {
628           server_entry->router = to;
629           server_entry->connection = to->connection;
630         }
631         if (!silc_idcache_list_next(list, &id_cache))
632           break;
633       }
634     }
635     silc_idcache_list_free(list);
636   }
637
638   if (silc_idcache_get_all(server->global_list->servers, &list)) {
639     if (silc_idcache_list_first(list, &id_cache)) {
640       while (id_cache) {
641         server_entry = (SilcServerEntry)id_cache->context;
642         if (server_entry->router == from) {
643           server_entry->router = to;
644           server_entry->connection = to->connection;
645         }
646         if (!silc_idcache_list_next(list, &id_cache))
647           break;
648       }
649     }
650     silc_idcache_list_free(list);
651   }
652 }
653
654 /* Removes channels that are from `from. */
655
656 void silc_server_remove_channels_by_server(SilcServer server, 
657                                            SilcServerEntry from)
658 {
659   SilcIDCacheList list = NULL;
660   SilcIDCacheEntry id_cache = NULL;
661   SilcChannelEntry channel = NULL;
662
663   SILC_LOG_DEBUG(("Start"));
664
665   if (silc_idcache_get_all(server->global_list->channels, &list)) {
666     if (silc_idcache_list_first(list, &id_cache)) {
667       while (id_cache) {
668         channel = (SilcChannelEntry)id_cache->context;
669         if (channel->router == from)
670           silc_idlist_del_channel(server->global_list, channel);
671         if (!silc_idcache_list_next(list, &id_cache))
672           break;
673       }
674     }
675     silc_idcache_list_free(list);
676   }
677 }
678
679 /* Updates channels that are from `from' to be originated from `to'.  */
680
681 void silc_server_update_channels_by_server(SilcServer server, 
682                                            SilcServerEntry from,
683                                            SilcServerEntry to)
684 {
685   SilcIDCacheList list = NULL;
686   SilcIDCacheEntry id_cache = NULL;
687   SilcChannelEntry channel = NULL;
688
689   SILC_LOG_DEBUG(("Start"));
690
691   if (silc_idcache_get_all(server->global_list->channels, &list)) {
692     if (silc_idcache_list_first(list, &id_cache)) {
693       while (id_cache) {
694         channel = (SilcChannelEntry)id_cache->context;
695         if (channel->router == from)
696           channel->router = to;
697         if (!silc_idcache_list_next(list, &id_cache))
698           break;
699       }
700     }
701     silc_idcache_list_free(list);
702   }
703 }
704
705 /* Checks whether given channel has global users.  If it does this returns
706    TRUE and FALSE if there is only locally connected clients on the channel. */
707
708 bool silc_server_channel_has_global(SilcChannelEntry channel)
709 {
710   SilcChannelClientEntry chl;
711   SilcHashTableList htl;
712
713   silc_hash_table_list(channel->user_list, &htl);
714   while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
715     if (chl->client->router) {
716       silc_hash_table_list_reset(&htl);
717       return TRUE;
718     }
719   }
720   silc_hash_table_list_reset(&htl);
721
722   return FALSE;
723 }
724
725 /* Checks whether given channel has locally connected users.  If it does this
726    returns TRUE and FALSE if there is not one locally connected client. */
727
728 bool silc_server_channel_has_local(SilcChannelEntry channel)
729 {
730   SilcChannelClientEntry chl;
731   SilcHashTableList htl;
732
733   silc_hash_table_list(channel->user_list, &htl);
734   while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
735     if (!chl->client->router) {
736       silc_hash_table_list_reset(&htl);
737       return TRUE;
738     }
739   }
740   silc_hash_table_list_reset(&htl);
741
742   return FALSE;
743 }
744
745 /* Returns TRUE if the given client is on the channel.  FALSE if not. 
746    This works because we assure that the user list on the channel is
747    always in up to date thus we can only check the channel list from 
748    `client' which is faster than checking the user list from `channel'. */
749
750 bool silc_server_client_on_channel(SilcClientEntry client,
751                                    SilcChannelEntry channel,
752                                    SilcChannelClientEntry *chl)
753 {
754   if (!client || !channel)
755     return FALSE;
756
757   return silc_hash_table_find(client->channels, channel, NULL, 
758                               (void **)chl);
759 }
760
761 /* Checks string for bad characters and returns TRUE if they are found. */
762
763 bool silc_server_name_bad_chars(const char *name, SilcUInt32 name_len)
764 {
765   int i;
766
767   for (i = 0; i < name_len; i++) {
768     if (!isascii(name[i]))
769       return TRUE;
770     if (name[i] <= 32) return TRUE;
771     if (name[i] == ' ') return TRUE;
772     if (name[i] == '*') return TRUE;
773     if (name[i] == '?') return TRUE;
774     if (name[i] == ',') return TRUE;
775   }
776
777   return FALSE;
778 }
779
780 /* Modifies the `name' if it includes bad characters and returns new
781    allocated name that does not include bad characters. */
782
783 char *silc_server_name_modify_bad(const char *name, SilcUInt32 name_len)
784 {
785   int i;
786   char *newname = strdup(name);
787
788   for (i = 0; i < name_len; i++) {
789     if (!isascii(newname[i])) newname[i] = '_';
790     if (newname[i] <= 32) newname[i] = '_';
791     if (newname[i] == ' ') newname[i] = '_';
792     if (newname[i] == '*') newname[i] = '_';
793     if (newname[i] == '?') newname[i] = '_';
794     if (newname[i] == ',') newname[i] = '_';
795   }
796
797   return newname;
798 }
799
800 /* Find number of sockets by IP address indicated by `ip'. Returns 0 if
801    socket connections with the IP address does not exist. */
802
803 SilcUInt32 silc_server_num_sockets_by_ip(SilcServer server, const char *ip,
804                                          SilcSocketType type)
805 {
806   int i, count;
807
808   for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
809     if (server->sockets[i] && !strcmp(server->sockets[i]->ip, ip) &&
810         server->sockets[i]->type == type)
811       count++;
812   }
813
814   return count;
815 }
816
817 /* Find number of sockets by IP address indicated by remote host, indicatd
818    by `ip' or `hostname', `port', and `type'.  Returns 0 if socket connections
819    does not exist. If `ip' is provided then `hostname' is ignored. */
820
821 SilcUInt32 silc_server_num_sockets_by_remote(SilcServer server, 
822                                              const char *ip,
823                                              const char *hostname,
824                                              SilcUInt16 port,
825                                              SilcSocketType type)
826 {
827   int i, count;
828
829   if (!ip && !hostname)
830     return 0;
831
832   for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
833     if (server->sockets[i] && 
834         ((ip && !strcmp(server->sockets[i]->ip, ip)) ||
835          (hostname && !strcmp(server->sockets[i]->hostname, hostname))) &&
836         server->sockets[i]->port == port &&
837         server->sockets[i]->type == type)
838       count++;
839   }
840
841   return count;
842 }
843
844 /* Finds locally cached public key by the public key received in the SKE. 
845    If we have it locally cached then we trust it and will use it in the
846    authentication protocol.  Returns the locally cached public key or NULL
847    if we do not find the public key.  */
848
849 SilcPublicKey silc_server_find_public_key(SilcServer server, 
850                                           SilcHashTable local_public_keys,
851                                           SilcPublicKey remote_public_key)
852 {
853   SilcPublicKey cached_key;
854
855   SILC_LOG_DEBUG(("Find remote public key (%d keys in local cache)",
856                   silc_hash_table_count(local_public_keys)));
857
858   if (!silc_hash_table_find_ext(local_public_keys, remote_public_key,
859                                 (void **)&cached_key, NULL, 
860                                 silc_hash_public_key, NULL,
861                                 silc_hash_public_key_compare, NULL)) {
862     SILC_LOG_ERROR(("Public key not found"));
863     return NULL;
864   }
865
866   SILC_LOG_DEBUG(("Found public key"));
867
868   return cached_key;
869 }
870
871 /* This returns the first public key from the table of public keys.  This
872    is used only in cases where single public key exists in the table and
873    we want to get a pointer to it.  For public key tables that has multiple
874    keys in it the silc_server_find_public_key must be used. */
875
876 SilcPublicKey silc_server_get_public_key(SilcServer server,
877                                          SilcHashTable local_public_keys)
878 {
879   SilcPublicKey cached_key;
880   SilcHashTableList htl;
881
882   SILC_LOG_DEBUG(("Start"));
883
884   assert(silc_hash_table_count(local_public_keys) < 2);
885
886   silc_hash_table_list(local_public_keys, &htl);
887   if (!silc_hash_table_get(&htl, NULL, (void **)&cached_key))
888     return NULL;
889   silc_hash_table_list_reset(&htl);
890
891   return cached_key;
892 }
893
894 /* Check whether the connection `sock' is allowed to connect to us.  This
895    checks for example whether there is too much connections for this host,
896    and required version for the host etc. */
897
898 bool silc_server_connection_allowed(SilcServer server, 
899                                     SilcSocketConnection sock,
900                                     SilcSocketType type,
901                                     SilcServerConfigConnParams *global,
902                                     SilcServerConfigConnParams *params,
903                                     SilcSKE ske)
904 {
905   SilcUInt32 conn_number = (type == SILC_SOCKET_TYPE_CLIENT ?
906                             server->stat.my_clients :
907                             type == SILC_SOCKET_TYPE_SERVER ?
908                             server->stat.my_servers :
909                             server->stat.my_routers);
910   SilcUInt32 num_sockets, max_hosts, max_per_host;
911   SilcUInt32 r_protocol_version, l_protocol_version;
912   SilcUInt32 r_software_version, l_software_version;
913   char *r_vendor_version = NULL, *l_vendor_version;
914
915   /* Check version */
916
917   l_protocol_version = 
918     silc_version_to_num(params && params->version_protocol ? 
919                         params->version_protocol : 
920                         global->version_protocol);
921   l_software_version = 
922     silc_version_to_num(params && params->version_software ? 
923                         params->version_software : 
924                         global->version_software);
925   l_vendor_version = (params && params->version_software_vendor ? 
926                       params->version_software_vendor : 
927                       global->version_software_vendor);
928   
929   if (ske && silc_ske_parse_version(ske, &r_protocol_version, NULL,
930                                     &r_software_version, NULL,
931                                     &r_vendor_version)) {
932     sock->version = r_protocol_version;
933
934     /* Match protocol version */
935     if (l_protocol_version && r_protocol_version &&
936         r_protocol_version < l_protocol_version) {
937       SILC_LOG_INFO(("Connection %s (%s) is too old version",
938                      sock->hostname, sock->ip));
939       silc_server_disconnect_remote(server, sock, 
940                                     "Server closed connection: "
941                                     "You support too old protocol version");
942       return FALSE;
943     }
944
945     /* Math software version */
946     if (l_software_version && r_software_version &&
947         r_software_version < l_software_version) {
948       SILC_LOG_INFO(("Connection %s (%s) is too old version",
949                      sock->hostname, sock->ip));
950       silc_server_disconnect_remote(server, sock, 
951                                     "Server closed connection: "
952                                     "You support too old software version");
953       return FALSE;
954     }
955
956     /* Regex match vendor version */
957     if (l_vendor_version && r_vendor_version && 
958         !silc_string_match(l_vendor_version, r_vendor_version)) {
959       SILC_LOG_INFO(("Connection %s (%s) is unsupported version",
960                      sock->hostname, sock->ip));
961       silc_server_disconnect_remote(server, sock, 
962                                     "Server closed connection: "
963                                     "Your software is not supported");
964       return FALSE;
965     }
966   }
967   silc_free(r_vendor_version);
968
969   /* Check for maximum connections limit */
970
971   num_sockets = silc_server_num_sockets_by_ip(server, sock->ip, type);
972   max_hosts = (params ? params->connections_max : global->connections_max);
973   max_per_host = (params ? params->connections_max_per_host :
974                   global->connections_max_per_host);
975
976   if (max_hosts && conn_number >= max_hosts) {
977     SILC_LOG_INFO(("Server is full, closing %s (%s) connection",
978                    sock->hostname, sock->ip));
979     silc_server_disconnect_remote(server, sock, 
980                                   "Server closed connection: "
981                                   "Server is full, try again later");
982     return FALSE;
983   }
984
985   if (num_sockets >= max_per_host) {
986     SILC_LOG_INFO(("Too many connections from %s (%s), closing connection",
987                    sock->hostname, sock->ip));
988     silc_server_disconnect_remote(server, sock, 
989                                   "Server closed connection: "
990                                   "Too many connections from your host");
991     return FALSE;
992   }
993
994   return TRUE;
995 }
996
997 /* Checks that client has rights to add or remove channel modes. If any
998    of the checks fails FALSE is returned. */
999
1000 bool silc_server_check_cmode_rights(SilcServer server,
1001                                     SilcChannelEntry channel,
1002                                     SilcChannelClientEntry client,
1003                                     SilcUInt32 mode)
1004 {
1005   bool is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1006   bool is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1007
1008   /* Check whether has rights to change anything */
1009   if (!is_op && !is_fo)
1010     return FALSE;
1011
1012   /* Check whether has rights to change everything */
1013   if (is_op && is_fo)
1014     return TRUE;
1015
1016   /* We know that client is channel operator, check that they are not
1017      changing anything that requires channel founder rights. Rest of the
1018      modes are available automatically for channel operator. */
1019
1020   if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1021     if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
1022       if (is_op && !is_fo)
1023         return FALSE;
1024   } else {
1025     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1026       if (is_op && !is_fo)
1027         return FALSE;
1028     }
1029   }
1030   
1031   if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1032     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
1033       if (is_op && !is_fo)
1034         return FALSE;
1035   } else {
1036     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1037       if (is_op && !is_fo)
1038         return FALSE;
1039     }
1040   }
1041
1042   if (mode & SILC_CHANNEL_MODE_CIPHER) {
1043     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
1044       if (is_op && !is_fo)
1045         return FALSE;
1046   } else {
1047     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1048       if (is_op && !is_fo)
1049         return FALSE;
1050     }
1051   }
1052   
1053   if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1054     if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
1055       if (is_op && !is_fo)
1056         return FALSE;
1057   } else {
1058     if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1059       if (is_op && !is_fo)
1060         return FALSE;
1061     }
1062   }
1063   
1064   if (mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1065     if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS))
1066       if (is_op && !is_fo)
1067         return FALSE;
1068   } else {
1069     if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1070       if (is_op && !is_fo)
1071         return FALSE;
1072     }
1073   }
1074   
1075   if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1076     if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS))
1077       if (is_op && !is_fo)
1078         return FALSE;
1079   } else {
1080     if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1081       if (is_op && !is_fo)
1082         return FALSE;
1083     }
1084   }
1085   
1086   return TRUE;
1087 }
1088
1089 /* Check that the client has rights to change its user mode.  Returns
1090    FALSE if setting some mode is not allowed. */
1091
1092 bool silc_server_check_umode_rights(SilcServer server,
1093                                     SilcClientEntry client,
1094                                     SilcUInt32 mode)
1095 {
1096   bool server_op = FALSE, router_op = FALSE;
1097
1098   if (mode & SILC_UMODE_SERVER_OPERATOR) {
1099     /* Cannot set server operator mode (must use OPER command) */
1100     if (!(client->mode & SILC_UMODE_SERVER_OPERATOR))
1101       return FALSE;
1102   } else {
1103     /* Remove the server operator rights */
1104     if (client->mode & SILC_UMODE_SERVER_OPERATOR)
1105       server_op = TRUE;
1106   }
1107
1108   if (mode & SILC_UMODE_ROUTER_OPERATOR) {
1109     /* Cannot set router operator mode (must use SILCOPER command) */
1110     if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR))
1111       return FALSE;
1112   } else {
1113     /* Remove the router operator rights */
1114     if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
1115       router_op = TRUE;
1116   }
1117
1118   if (server_op)
1119     SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR);
1120   if (router_op)
1121     SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR);
1122
1123   return TRUE;
1124 }
1125
1126 /* This function is used to send the notify packets and motd to the
1127    incoming client connection. */
1128
1129 void silc_server_send_connect_notifys(SilcServer server,
1130                                       SilcSocketConnection sock,
1131                                       SilcClientEntry client)
1132 {
1133   SilcIDListData idata = (SilcIDListData)client;
1134
1135   /* Send some nice info to the client */
1136   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1137                           ("Welcome to the SILC Network %s",
1138                            client->username));
1139   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1140                           ("Your host is %s, running version %s",
1141                            server->server_name, server_version));
1142
1143   if (server->stat.clients && server->stat.servers + 1)
1144     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1145                             ("There are %d clients on %d servers in SILC "
1146                              "Network", server->stat.clients,
1147                              server->stat.servers + 1));
1148   if (server->stat.cell_clients && server->stat.cell_servers + 1)
1149     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1150                             ("There are %d clients on %d server in our cell",
1151                              server->stat.cell_clients,
1152                              server->stat.cell_servers + 1));
1153   if (server->server_type == SILC_ROUTER) {
1154     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1155                             ("I have %d clients, %d channels, %d servers and "
1156                              "%d routers",
1157                              server->stat.my_clients, 
1158                              server->stat.my_channels,
1159                              server->stat.my_servers,
1160                              server->stat.my_routers));
1161   } else {
1162     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1163                             ("I have %d clients and %d channels formed",
1164                              server->stat.my_clients,
1165                              server->stat.my_channels));
1166   }
1167
1168   if (server->stat.server_ops || server->stat.router_ops)
1169     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1170                             ("There are %d server operators and %d router "
1171                              "operators online",
1172                              server->stat.server_ops,
1173                              server->stat.router_ops));
1174   if (server->stat.my_router_ops + server->stat.my_server_ops)
1175     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1176                             ("I have %d operators online",
1177                              server->stat.my_router_ops +
1178                              server->stat.my_server_ops));
1179
1180   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1181                           ("Your connection is secured with %s cipher, "
1182                            "key length %d bits",
1183                            idata->send_key->cipher->name,
1184                            idata->send_key->cipher->key_len));
1185   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1186                           ("Your current nickname is %s",
1187                            client->nickname));
1188
1189   /* Send motd */
1190   silc_server_send_motd(server, sock);
1191 }
1192
1193 /* Kill the client indicated by `remote_client' sending KILLED notify
1194    to the client, to all channels client has joined and to primary
1195    router if needed.  The killed client is also removed from all channels. */
1196
1197 void silc_server_kill_client(SilcServer server,
1198                              SilcClientEntry remote_client,
1199                              const char *comment,
1200                              void *killer_id,
1201                              SilcIdType killer_id_type)
1202 {
1203   SilcBuffer killed, killer;
1204
1205   /* Send the KILL notify packets. First send it to the channel, then
1206      to our primary router and then directly to the client who is being
1207      killed right now. */
1208
1209   killed = silc_id_payload_encode(remote_client->id, SILC_ID_CLIENT);
1210   killer = silc_id_payload_encode(killer_id, killer_id_type);
1211
1212   /* Send KILLED notify to the channels. It is not sent to the client
1213      as it will be sent differently destined directly to the client and not
1214      to the channel. */
1215   silc_server_send_notify_on_channels(server, remote_client, 
1216                                       remote_client, SILC_NOTIFY_TYPE_KILLED,
1217                                       3, killed->data, killed->len,
1218                                       comment, comment ? strlen(comment) : 0,
1219                                       killer->data, killer->len);
1220
1221   /* Send KILLED notify to primary route */
1222   if (!server->standalone)
1223     silc_server_send_notify_killed(server, server->router->connection, TRUE,
1224                                    remote_client->id, comment, 
1225                                    killer_id, killer_id_type);
1226
1227   /* Send KILLED notify to the client directly */
1228   if (remote_client->connection || remote_client->router)
1229     silc_server_send_notify_killed(server, remote_client->connection ? 
1230                                    remote_client->connection : 
1231                                    remote_client->router->connection, FALSE,
1232                                    remote_client->id, comment, 
1233                                    killer_id, killer_id_type);
1234
1235   /* Remove the client from all channels. This generates new keys to the
1236      channels as well. */
1237   silc_server_remove_from_channels(server, NULL, remote_client, FALSE, 
1238                                    NULL, TRUE);
1239
1240   /* Remove the client entry, If it is locally connected then we will also
1241      disconnect the client here */
1242   if (remote_client->connection) {
1243     /* Remove locally conneted client */
1244     SilcSocketConnection sock = remote_client->connection;
1245     silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
1246     silc_server_close_connection(server, sock);
1247   } else {
1248     /* Update statistics */
1249     server->stat.clients--;
1250     server->stat.my_clients--;
1251     if (server->stat.cell_clients)
1252       server->stat.cell_clients--;
1253     SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
1254     SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
1255
1256     /* Remove remote client */
1257     if (!silc_idlist_del_client(server->global_list, remote_client)) {
1258       /* Remove this client from watcher list if it is */
1259       silc_server_del_from_watcher_list(server, remote_client);
1260
1261       silc_idlist_del_client(server->local_list, remote_client);  
1262     }
1263   }
1264
1265   silc_buffer_free(killer);
1266   silc_buffer_free(killed);
1267 }
1268
1269 typedef struct {
1270   SilcServer server;
1271   SilcClientEntry client;
1272   SilcNotifyType notify;
1273   const char *new_nick;
1274 } WatcherNotifyContext;
1275
1276 static void 
1277 silc_server_check_watcher_list_foreach(void *key, void *context, 
1278                                        void *user_context)
1279 {
1280   WatcherNotifyContext *notify = user_context;
1281   SilcClientEntry entry = context;
1282   SilcSocketConnection sock;
1283
1284   if (entry == notify->client)
1285     return;
1286
1287   sock = silc_server_get_client_route(notify->server, NULL, 0, entry->id,
1288                                       NULL, NULL);
1289   if (sock) {
1290     SILC_LOG_DEBUG(("Sending WATCH notify to %s",
1291                     silc_id_render(entry->id, SILC_ID_CLIENT)));
1292
1293     /* Send the WATCH notify */
1294     silc_server_send_notify_watch(notify->server, sock, entry, 
1295                                   notify->client, 
1296                                   notify->new_nick ? notify->new_nick :
1297                                   notify->client->nickname, notify->notify);
1298   }
1299 }
1300
1301 /* This function checks whether the `client' nickname is being watched
1302    by someone, and notifies the watcher of the notify change of notify
1303    type indicated by `notify'. */
1304
1305 bool silc_server_check_watcher_list(SilcServer server,
1306                                     SilcClientEntry client,
1307                                     const char *new_nick,
1308                                     SilcNotifyType notify)
1309 {
1310   unsigned char hash[16];
1311   WatcherNotifyContext n;
1312
1313   SILC_LOG_DEBUG(("Start"));
1314
1315   /* If the watching is rejected by the client do nothing */
1316   if (client->mode & SILC_UMODE_REJECT_WATCHING)
1317     return FALSE;
1318
1319   /* Make hash from the nick, or take it from Client ID */
1320   if (client->nickname) {
1321     char nick[128 + 1];
1322     memset(nick, 0, sizeof(nick));
1323     silc_to_lower(client->nickname, nick, sizeof(nick) - 1);
1324     silc_hash_make(server->md5hash, nick, strlen(nick), hash);
1325   } else {
1326     memset(hash, 0, sizeof(hash));
1327     memcpy(hash, client->id->hash, sizeof(client->id->hash));
1328   }
1329
1330   n.server = server;
1331   n.client = client;
1332   n.new_nick = new_nick;
1333   n.notify = notify;
1334
1335   /* Send notify to all watchers */
1336   silc_hash_table_find_foreach(server->watcher_list, hash,
1337                                silc_server_check_watcher_list_foreach, &n);
1338
1339   return TRUE;
1340 }
1341
1342 /* Remove the `client' from watcher list. After calling this the `client'
1343    is not watching any nicknames. */
1344
1345 bool silc_server_del_from_watcher_list(SilcServer server,
1346                                        SilcClientEntry client)
1347 {
1348   SilcHashTableList htl;
1349   void *key;
1350   SilcClientEntry entry;
1351   bool found = FALSE;
1352
1353   silc_hash_table_list(server->watcher_list, &htl);
1354   while (silc_hash_table_get(&htl, &key, (void **)&entry)) {
1355     if (entry == client) {
1356       silc_hash_table_del_by_context(server->watcher_list, key, client);
1357
1358       SILC_LOG_DEBUG(("Removing %s from WATCH list",
1359                       silc_id_render(client->id, SILC_ID_CLIENT)));
1360
1361       /* Now check whether there still exists entries with this key, if not
1362          then free the key to not leak memory. */
1363       if (!silc_hash_table_find(server->watcher_list, key, NULL, NULL))
1364         silc_free(key);
1365
1366       found = TRUE;
1367     }
1368   }
1369   silc_hash_table_list_reset(&htl);
1370
1371   return found;
1372 }