Fixed topic annoucning, server signoff handling, added -D option,
[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   /* Send some nice info to the client */
1177   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1178                           ("Welcome to the SILC Network %s",
1179                            client->username));
1180   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1181                           ("Your host is %s, running version %s",
1182                            server->server_name, server_version));
1183
1184   if (server->server_type == SILC_ROUTER) {
1185     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1186                             ("There are %d clients, %d servers and %d "
1187                              "routers in SILC Network",
1188                              server->stat.clients, server->stat.servers + 1,
1189                              server->stat.routers));
1190   } else {
1191     if (server->stat.clients && server->stat.servers + 1)
1192       SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1193                               ("There are %d clients, %d servers and %d "
1194                                "routers in SILC Network",
1195                                server->stat.clients, server->stat.servers + 1,
1196                                (server->standalone ? 0 :
1197                                 !server->stat.routers ? 1 :
1198                                 server->stat.routers)));
1199   }
1200
1201   if (server->stat.cell_clients && server->stat.cell_servers + 1)
1202     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1203                             ("There are %d clients on %d server in our cell",
1204                              server->stat.cell_clients,
1205                              server->stat.cell_servers + 1));
1206   if (server->server_type == SILC_ROUTER) {
1207     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1208                             ("I have %d clients, %d channels, %d servers and "
1209                              "%d routers",
1210                              server->stat.my_clients, 
1211                              server->stat.my_channels,
1212                              server->stat.my_servers,
1213                              server->stat.my_routers));
1214   } else {
1215     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1216                             ("I have %d clients and %d channels formed",
1217                              server->stat.my_clients,
1218                              server->stat.my_channels));
1219   }
1220
1221   if (server->stat.server_ops || server->stat.router_ops)
1222     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1223                             ("There are %d server operators and %d router "
1224                              "operators online",
1225                              server->stat.server_ops,
1226                              server->stat.router_ops));
1227   if (server->stat.my_router_ops + server->stat.my_server_ops)
1228     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1229                             ("I have %d operators online",
1230                              server->stat.my_router_ops +
1231                              server->stat.my_server_ops));
1232
1233   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1234                           ("Your connection is secured with %s cipher, "
1235                            "key length %d bits",
1236                            idata->send_key->cipher->name,
1237                            idata->send_key->cipher->key_len));
1238   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1239                           ("Your current nickname is %s",
1240                            client->nickname));
1241
1242   /* Send motd */
1243   silc_server_send_motd(server, sock);
1244 }
1245
1246 /* Kill the client indicated by `remote_client' sending KILLED notify
1247    to the client, to all channels client has joined and to primary
1248    router if needed.  The killed client is also removed from all channels. */
1249
1250 void silc_server_kill_client(SilcServer server,
1251                              SilcClientEntry remote_client,
1252                              const char *comment,
1253                              void *killer_id,
1254                              SilcIdType killer_id_type)
1255 {
1256   SilcBuffer killed, killer;
1257
1258   SILC_LOG_DEBUG(("Killing client %s", 
1259                   silc_id_render(remote_client->id, SILC_ID_CLIENT)));
1260
1261   /* Send the KILL notify packets. First send it to the channel, then
1262      to our primary router and then directly to the client who is being
1263      killed right now. */
1264
1265   killed = silc_id_payload_encode(remote_client->id, SILC_ID_CLIENT);
1266   killer = silc_id_payload_encode(killer_id, killer_id_type);
1267
1268   /* Send KILLED notify to the channels. It is not sent to the client
1269      as it will be sent differently destined directly to the client and not
1270      to the channel. */
1271   silc_server_send_notify_on_channels(server, remote_client, 
1272                                       remote_client, SILC_NOTIFY_TYPE_KILLED,
1273                                       3, killed->data, killed->len,
1274                                       comment, comment ? strlen(comment) : 0,
1275                                       killer->data, killer->len);
1276
1277   /* Send KILLED notify to primary route */
1278   if (!server->standalone)
1279     silc_server_send_notify_killed(server, server->router->connection, TRUE,
1280                                    remote_client->id, comment, 
1281                                    killer_id, killer_id_type);
1282
1283   /* Send KILLED notify to the client directly */
1284   if (remote_client->connection || remote_client->router)
1285     silc_server_send_notify_killed(server, remote_client->connection ? 
1286                                    remote_client->connection : 
1287                                    remote_client->router->connection, FALSE,
1288                                    remote_client->id, comment, 
1289                                    killer_id, killer_id_type);
1290
1291   /* Remove the client from all channels. This generates new keys to the
1292      channels as well. */
1293   silc_server_remove_from_channels(server, NULL, remote_client, FALSE, 
1294                                    NULL, TRUE);
1295
1296   /* Remove the client entry, If it is locally connected then we will also
1297      disconnect the client here */
1298   if (remote_client->connection) {
1299     /* Remove locally conneted client */
1300     SilcSocketConnection sock = remote_client->connection;
1301     silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
1302     silc_server_close_connection(server, sock);
1303   } else {
1304     /* Update statistics */
1305     server->stat.clients--;
1306     server->stat.my_clients--;
1307     if (server->stat.cell_clients)
1308       server->stat.cell_clients--;
1309     SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
1310     SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
1311
1312     /* Remove remote client */
1313     if (!silc_idlist_del_client(server->global_list, remote_client)) {
1314       /* Remove this client from watcher list if it is */
1315       silc_server_del_from_watcher_list(server, remote_client);
1316       silc_idlist_del_client(server->local_list, remote_client);  
1317     }
1318   }
1319
1320   silc_buffer_free(killer);
1321   silc_buffer_free(killed);
1322 }
1323
1324 typedef struct {
1325   SilcServer server;
1326   SilcClientEntry client;
1327   SilcNotifyType notify;
1328   const char *new_nick;
1329 } WatcherNotifyContext;
1330
1331 static void 
1332 silc_server_check_watcher_list_foreach(void *key, void *context, 
1333                                        void *user_context)
1334 {
1335   WatcherNotifyContext *notify = user_context;
1336   SilcClientEntry entry = context;
1337   SilcSocketConnection sock;
1338
1339   if (entry == notify->client)
1340     return;
1341
1342   sock = silc_server_get_client_route(notify->server, NULL, 0, entry->id,
1343                                       NULL, NULL);
1344   if (sock) {
1345     SILC_LOG_DEBUG(("Sending WATCH notify to %s",
1346                     silc_id_render(entry->id, SILC_ID_CLIENT)));
1347
1348     /* Send the WATCH notify */
1349     silc_server_send_notify_watch(notify->server, sock, entry, 
1350                                   notify->client, 
1351                                   notify->new_nick ? notify->new_nick :
1352                                   (const char *)notify->client->nickname, 
1353                                   notify->notify);
1354   }
1355 }
1356
1357 /* This function checks whether the `client' nickname is being watched
1358    by someone, and notifies the watcher of the notify change of notify
1359    type indicated by `notify'. */
1360
1361 bool silc_server_check_watcher_list(SilcServer server,
1362                                     SilcClientEntry client,
1363                                     const char *new_nick,
1364                                     SilcNotifyType notify)
1365 {
1366   unsigned char hash[16];
1367   WatcherNotifyContext n;
1368
1369   SILC_LOG_DEBUG(("Start"));
1370
1371   /* If the watching is rejected by the client do nothing */
1372   if (client->mode & SILC_UMODE_REJECT_WATCHING)
1373     return FALSE;
1374
1375   /* Make hash from the nick, or take it from Client ID */
1376   if (client->nickname) {
1377     char nick[128 + 1];
1378     memset(nick, 0, sizeof(nick));
1379     silc_to_lower(client->nickname, nick, sizeof(nick) - 1);
1380     silc_hash_make(server->md5hash, nick, strlen(nick), hash);
1381   } else {
1382     memset(hash, 0, sizeof(hash));
1383     memcpy(hash, client->id->hash, sizeof(client->id->hash));
1384   }
1385
1386   n.server = server;
1387   n.client = client;
1388   n.new_nick = new_nick;
1389   n.notify = notify;
1390
1391   /* Send notify to all watchers */
1392   silc_hash_table_find_foreach(server->watcher_list, hash,
1393                                silc_server_check_watcher_list_foreach, &n);
1394
1395   return TRUE;
1396 }
1397
1398 /* Remove the `client' from watcher list. After calling this the `client'
1399    is not watching any nicknames. */
1400
1401 bool silc_server_del_from_watcher_list(SilcServer server,
1402                                        SilcClientEntry client)
1403 {
1404   SilcHashTableList htl;
1405   void *key;
1406   SilcClientEntry entry;
1407   bool found = FALSE;
1408
1409   silc_hash_table_list(server->watcher_list, &htl);
1410   while (silc_hash_table_get(&htl, &key, (void **)&entry)) {
1411     if (entry == client) {
1412       silc_hash_table_del_by_context(server->watcher_list, key, client);
1413
1414       SILC_LOG_DEBUG(("Removing %s from WATCH list",
1415                       silc_id_render(client->id, SILC_ID_CLIENT)));
1416
1417       /* Now check whether there still exists entries with this key, if not
1418          then free the key to not leak memory. */
1419       if (!silc_hash_table_find(server->watcher_list, key, NULL, NULL))
1420         silc_free(key);
1421
1422       found = TRUE;
1423     }
1424   }
1425   silc_hash_table_list_reset(&htl);
1426
1427   return found;
1428 }
1429
1430 /* Force the client indicated by `chl' to change the channel user mode
1431    on channel indicated by `channel' to `forced_mode'. */
1432
1433 bool silc_server_force_cumode_change(SilcServer server,
1434                                      SilcSocketConnection sock,
1435                                      SilcChannelEntry channel,
1436                                      SilcChannelClientEntry chl,
1437                                      SilcUInt32 forced_mode)
1438 {
1439   SilcBuffer idp1, idp2;
1440   unsigned char cumode[4];
1441
1442   SILC_LOG_DEBUG(("Start"));
1443
1444   if (sock)
1445     silc_server_send_notify_cumode(server, sock, FALSE, channel, forced_mode,
1446                                    server->id, SILC_ID_SERVER,
1447                                    chl->client->id, NULL);
1448
1449   idp1 = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1450   idp2 = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
1451   SILC_PUT32_MSB(forced_mode, cumode);
1452   silc_server_send_notify_to_channel(server, sock, channel, FALSE,
1453                                      SILC_NOTIFY_TYPE_CUMODE_CHANGE,
1454                                      3, idp1->data, idp1->len,
1455                                      cumode, sizeof(cumode),
1456                                      idp2->data, idp2->len);
1457   silc_buffer_free(idp1);
1458   silc_buffer_free(idp2);
1459
1460   return TRUE;
1461 }