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