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