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