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