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