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