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