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