updates.
[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 - 2001 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 /* Removes the client from channels and possibly removes the channels
25    as well.  After removing those channels that exist, their channel
26    keys are regnerated. This is called only by the function
27    silc_server_remove_clients_by_server. */
28
29 static void silc_server_remove_clients_channels(SilcServer server, 
30                                                 SilcSocketConnection sock,
31                                                 SilcClientEntry client,
32                                                 SilcHashTable channels)
33 {
34   SilcChannelEntry channel;
35   SilcChannelClientEntry chl;
36   SilcHashTableList htl;
37   SilcBuffer clidp;
38
39   SILC_LOG_DEBUG(("Start"));
40
41   if (!client || !client->id)
42     return;
43
44   clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
45
46   /* Remove the client from all channels. The client is removed from
47      the channels' user list. */
48   silc_hash_table_list(client->channels, &htl);
49   while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
50     channel = chl->channel;
51
52     /* Remove channel from client's channel list */
53     silc_hash_table_del(client->channels, channel);
54
55     /* Remove channel if there is no users anymore */
56     if (server->server_type == SILC_ROUTER &&
57         silc_hash_table_count(channel->user_list) < 2) {
58
59       if (silc_hash_table_find(channels, channel, NULL, NULL))
60         silc_hash_table_del(channels, channel);
61
62       if (channel->rekey)
63         silc_schedule_task_del_by_context(server->schedule, channel->rekey);
64
65       if (silc_idlist_del_channel(server->local_list, channel))
66         server->stat.my_channels--;
67       else 
68         silc_idlist_del_channel(server->global_list, channel);
69       continue;
70     }
71
72     /* Remove client from channel's client list */
73     silc_hash_table_del(channel->user_list, chl->client);
74     channel->user_count--;
75
76     /* If there is no global users on the channel anymore mark the channel
77        as local channel. Do not check if the removed client is local client. */
78     if (server->server_type != SILC_ROUTER && channel->global_users && 
79         chl->client->router && !silc_server_channel_has_global(channel))
80       channel->global_users = FALSE;
81
82     silc_free(chl);
83     server->stat.my_chanclients--;
84
85     /* If there is not at least one local user on the channel then we don't
86        need the channel entry anymore, we can remove it safely. */
87     if (server->server_type != SILC_ROUTER &&
88         !silc_server_channel_has_local(channel)) {
89
90       if (silc_hash_table_find(channels, channel, NULL, NULL))
91         silc_hash_table_del(channels, channel);
92
93       if (channel->rekey)
94         silc_schedule_task_del_by_context(server->schedule, channel->rekey);
95
96       if (channel->founder_key) {
97         /* The founder auth data exists, do not remove the channel entry */
98         SilcChannelClientEntry chl2;
99         SilcHashTableList htl2;
100
101         channel->disabled = TRUE;
102
103         silc_hash_table_list(channel->user_list, &htl2);
104         while (silc_hash_table_get(&htl2, NULL, (void *)&chl2)) {
105           silc_hash_table_del(chl2->client->channels, channel);
106           silc_hash_table_del(channel->user_list, chl2->client);
107           channel->user_count--;
108           silc_free(chl2);
109         }
110         silc_hash_table_list_reset(&htl2);
111         continue;
112       }
113
114       /* Remove the channel entry */
115       if (silc_idlist_del_channel(server->local_list, channel))
116         server->stat.my_channels--;
117       else 
118         silc_idlist_del_channel(server->global_list, channel);
119       continue;
120     }
121
122     /* Add the channel to the the channels list to regenerate the 
123        channel key */
124     if (!silc_hash_table_find(channels, channel, NULL, NULL))
125       silc_hash_table_add(channels, channel, channel);
126   }
127   silc_hash_table_list_reset(&htl);
128
129   silc_buffer_free(clidp);
130 }
131
132 /* This function is used to remove all client entries by the server `entry'.
133    This is called when the connection is lost to the server. In this case
134    we must invalidate all the client entries owned by the server `entry'. 
135    If the `server_signoff' is TRUE then the SERVER_SIGNOFF notify is
136    distributed to our local clients. */
137
138 bool silc_server_remove_clients_by_server(SilcServer server, 
139                                           SilcServerEntry entry,
140                                           bool server_signoff)
141 {
142   SilcIDCacheList list = NULL;
143   SilcIDCacheEntry id_cache = NULL;
144   SilcClientEntry client = NULL;
145   SilcBuffer idp;
146   SilcClientEntry *clients = NULL;
147   uint32 clients_c = 0;
148   unsigned char **argv = NULL;
149   uint32 *argv_lens = NULL, *argv_types = NULL, argc = 0;
150   SilcHashTableList htl;
151   SilcChannelEntry channel;
152   SilcHashTable channels;
153   int i;
154
155   SILC_LOG_DEBUG(("Start"));
156
157   /* Allocate the hash table that holds the channels that require
158      channel key re-generation after we've removed this server's clients
159      from the channels. */
160   channels = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL,
161                                    NULL, NULL, TRUE);
162
163   if (server_signoff) {
164     idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
165     argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
166     argv_lens = silc_realloc(argv_lens,  sizeof(*argv_lens) * (argc + 1));
167     argv_types = silc_realloc(argv_types, sizeof(*argv_types) * (argc + 1));
168     argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
169     memcpy(argv[argc], idp->data, idp->len);
170     argv_lens[argc] = idp->len;
171     argv_types[argc] = argc + 1;
172     argc++;
173     silc_buffer_free(idp);
174   }
175
176   if (silc_idcache_get_all(server->local_list->clients, &list)) {
177
178     if (silc_idcache_list_first(list, &id_cache)) {
179       while (id_cache) {
180         client = (SilcClientEntry)id_cache->context;
181         if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
182           if (!silc_idcache_list_next(list, &id_cache))
183             break;
184           else
185             continue;
186         }
187
188         if (client->router != entry) {
189           if (server_signoff) {
190             clients = silc_realloc(clients, 
191                                    sizeof(*clients) * (clients_c + 1));
192             clients[clients_c] = client;
193             clients_c++;
194           }
195
196           if (!silc_idcache_list_next(list, &id_cache))
197             break;
198           else
199             continue;
200         }
201
202         if (server_signoff) {
203           idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
204           argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
205           argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
206                                    (argc + 1));
207           argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
208                                     (argc + 1));
209           argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
210           memcpy(argv[argc], idp->data, idp->len);
211           argv_lens[argc] = idp->len;
212           argv_types[argc] = argc + 1;
213           argc++;
214           silc_buffer_free(idp);
215         }
216
217         /* Update statistics */
218         server->stat.clients--;
219         if (server->server_type == SILC_ROUTER)
220           server->stat.cell_clients--;
221         SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
222         SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
223
224         /* Remove the client entry */
225         silc_server_remove_clients_channels(server, NULL, client, channels);
226         if (!server_signoff) {
227           client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
228           id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
229         } else {
230           silc_idlist_del_client(server->local_list, client);
231         }
232
233         if (!silc_idcache_list_next(list, &id_cache))
234           break;
235       }
236     }
237     silc_idcache_list_free(list);
238   }
239   
240   if (silc_idcache_get_all(server->global_list->clients, &list)) {
241
242     if (silc_idcache_list_first(list, &id_cache)) {
243       while (id_cache) {
244         client = (SilcClientEntry)id_cache->context;
245         if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
246           if (!silc_idcache_list_next(list, &id_cache))
247             break;
248           else
249             continue;
250         }
251         
252         if (client->router != entry) {
253           if (server_signoff && client->connection) {
254             clients = silc_realloc(clients, 
255                                    sizeof(*clients) * (clients_c + 1));
256             clients[clients_c] = client;
257             clients_c++;
258           }
259
260           if (!silc_idcache_list_next(list, &id_cache))
261             break;
262           else
263             continue;
264         }
265
266         if (server_signoff) {
267           idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
268           argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
269           argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
270                                    (argc + 1));
271           argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
272                                     (argc + 1));
273           argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
274           memcpy(argv[argc], idp->data, idp->len);
275           argv_lens[argc] = idp->len;
276           argv_types[argc] = argc + 1;
277           argc++;
278           silc_buffer_free(idp);
279         }
280
281         /* Update statistics */
282         server->stat.clients--;
283         if (server->server_type == SILC_ROUTER)
284           server->stat.cell_clients--;
285         SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
286         SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
287
288         /* Remove the client entry */
289         silc_server_remove_clients_channels(server, NULL, client, channels);
290         if (!server_signoff) {
291           client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
292           id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
293         } else {
294           silc_idlist_del_client(server->global_list, client);
295         }
296
297         if (!silc_idcache_list_next(list, &id_cache))
298           break;
299       }
300     }
301     silc_idcache_list_free(list);
302   }
303
304   /* Send the SERVER_SIGNOFF notify */
305   if (server_signoff) {
306     SilcBuffer args, not;
307
308     /* Send SERVER_SIGNOFF notify to our primary router */
309     if (!server->standalone && server->router &&
310         server->router != entry) {
311       args = silc_argument_payload_encode(1, argv, argv_lens,
312                                           argv_types);
313       silc_server_send_notify_args(server, 
314                                    server->router->connection,
315                                    server->server_type == SILC_SERVER ? 
316                                    FALSE : TRUE, 
317                                    SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
318                                    argc, args);
319       silc_buffer_free(args);
320     }
321
322     /* Send to local clients. We also send the list of client ID's that
323        is to be removed for those servers that would like to use that list. */
324     args = silc_argument_payload_encode(argc, argv, argv_lens,
325                                         argv_types);
326     not = silc_notify_payload_encode_args(SILC_NOTIFY_TYPE_SERVER_SIGNOFF, 
327                                           argc, args);
328     silc_server_packet_send_clients(server, clients, clients_c,
329                                     SILC_PACKET_NOTIFY, 0, FALSE,
330                                     not->data, not->len, FALSE);
331
332     silc_free(clients);
333     silc_buffer_free(args);
334     silc_buffer_free(not);
335     for (i = 0; i < argc; i++)
336       silc_free(argv[i]);
337     silc_free(argv);
338     silc_free(argv_lens);
339     silc_free(argv_types);
340   }
341
342   /* We must now re-generate the channel key for all channels that had
343      this server's client(s) on the channel. As they left the channel we
344      must re-generate the channel key. */
345   silc_hash_table_list(channels, &htl);
346   while (silc_hash_table_get(&htl, NULL, (void *)&channel)) {
347     if (!silc_server_create_channel_key(server, channel, 0)) {
348       silc_hash_table_list_reset(&htl);
349       silc_hash_table_free(channels);
350       return FALSE;
351     }
352
353     /* Do not send the channel key if private channel key mode is set */
354     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY)
355       continue;
356
357     silc_server_send_channel_key(server, NULL, channel, 
358                                  server->server_type == SILC_ROUTER ? 
359                                  FALSE : !server->standalone);
360   }
361   silc_hash_table_list_reset(&htl);
362   silc_hash_table_free(channels);
363
364   return TRUE;
365 }
366
367 static SilcServerEntry
368 silc_server_update_clients_by_real_server(SilcServer server,
369                                           SilcServerEntry from,
370                                           SilcClientEntry client,
371                                           bool local,
372                                           SilcIDCacheEntry client_cache)
373 {
374   SilcServerEntry server_entry;
375   SilcIDCacheEntry id_cache = NULL;
376   SilcIDCacheList list;
377
378   if (!silc_idcache_get_all(server->local_list->servers, &list))
379     return NULL;
380
381   if (silc_idcache_list_first(list, &id_cache)) {
382     while (id_cache) {
383       server_entry = (SilcServerEntry)id_cache->context;
384       if (server_entry != from &&
385           SILC_ID_COMPARE(server_entry->id, client->id, 
386                           client->id->ip.data_len)) {
387         SILC_LOG_DEBUG(("Found (local) %s",
388                         silc_id_render(server_entry->id, SILC_ID_SERVER)));
389
390         if (!server_entry->data.send_key && server_entry->router) {
391           SILC_LOG_DEBUG(("Server not locally connected, use its router"));
392           /* If the client is not marked as local then move it to local list
393              since the server is local. */
394           if (!local) {
395             SILC_LOG_DEBUG(("Moving client to local list"));
396             silc_idcache_add(server->local_list->clients, client_cache->name,
397                              client_cache->id, client_cache->context,
398                              client_cache->expire, NULL);
399             silc_idcache_del_by_context(server->global_list->clients, client);
400           }
401           server_entry = server_entry->router;
402         } else {
403           /* If the client is not marked as local then move it to local list
404              since the server is local. */
405           if (server_entry->server_type != SILC_BACKUP_ROUTER && !local) {
406             SILC_LOG_DEBUG(("Moving client to local list"));
407             silc_idcache_add(server->local_list->clients, client_cache->name,
408                              client_cache->id, client_cache->context,
409                              client_cache->expire, NULL);
410             silc_idcache_del_by_context(server->global_list->clients, client);
411           }
412         }
413
414         silc_idcache_list_free(list);
415         return server_entry;
416       }
417
418       if (!silc_idcache_list_next(list, &id_cache))
419         break;
420     }
421   }
422
423   silc_idcache_list_free(list);
424
425   if (!silc_idcache_get_all(server->global_list->servers, &list))
426     return NULL;
427
428   if (silc_idcache_list_first(list, &id_cache)) {
429     while (id_cache) {
430       server_entry = (SilcServerEntry)id_cache->context;
431       if (server_entry != from &&
432           SILC_ID_COMPARE(server_entry->id, client->id, 
433                           client->id->ip.data_len)) {
434         SILC_LOG_DEBUG(("Found (global) %s",
435                         silc_id_render(server_entry->id, SILC_ID_SERVER)));
436
437         if (!server_entry->data.send_key && server_entry->router) {
438           SILC_LOG_DEBUG(("Server not locally connected, use its router"));
439           /* If the client is marked as local then move it to global list
440              since the server is global. */
441           if (local) {
442             SILC_LOG_DEBUG(("Moving client to global list"));
443             silc_idcache_add(server->global_list->clients, client_cache->name,
444                              client_cache->id, client_cache->context,
445                              client_cache->expire, NULL);
446             silc_idcache_del_by_context(server->local_list->clients, client);
447           }
448           server_entry = server_entry->router;
449         } else {
450           /* If the client is marked as local then move it to global list
451              since the server is global. */
452           if (server_entry->server_type != SILC_BACKUP_ROUTER && local) {
453             SILC_LOG_DEBUG(("Moving client to global list"));
454             silc_idcache_add(server->global_list->clients, client_cache->name,
455                              client_cache->id, client_cache->context,
456                              client_cache->expire, NULL);
457             silc_idcache_del_by_context(server->local_list->clients, client);
458           }
459         }
460
461         silc_idcache_list_free(list);
462         return server_entry;
463       }
464
465       if (!silc_idcache_list_next(list, &id_cache))
466         break;
467     }
468   }
469
470   silc_idcache_list_free(list);
471
472   return NULL;
473 }
474
475 /* Updates the clients that are originated from the `from' to be originated
476    from the `to'. If the `resolve_real_server' is TRUE then this will
477    attempt to figure out which clients really are originated from the
478    `from' and which are originated from a server that we have connection
479    to, when we've acting as backup router. If it is FALSE the `to' will
480    be the new source. This function also removes the clients that are
481    *really* originated from `from' if `remove_from' is TRUE. These are
482    clients that the `from' owns, and not just clients that are behind
483    the `from'. */
484
485 void silc_server_update_clients_by_server(SilcServer server, 
486                                           SilcServerEntry from,
487                                           SilcServerEntry to,
488                                           bool resolve_real_server,
489                                           bool remove_from)
490 {
491   SilcIDCacheList list = NULL;
492   SilcIDCacheEntry id_cache = NULL;
493   SilcClientEntry client = NULL;
494   bool local;
495
496   SILC_LOG_DEBUG(("Start"));
497
498   SILC_LOG_DEBUG(("Updating %s", silc_id_render(from->id,
499                                                 SILC_ID_SERVER)));
500   SILC_LOG_DEBUG(("to %s", silc_id_render(to->id,
501                                           SILC_ID_SERVER)));
502
503
504   local = FALSE;
505   if (silc_idcache_get_all(server->global_list->clients, &list)) {
506     if (silc_idcache_list_first(list, &id_cache)) {
507       while (id_cache) {
508         client = (SilcClientEntry)id_cache->context;
509         if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
510           if (!silc_idcache_list_next(list, &id_cache))
511             break;
512           else
513             continue;
514         }
515
516         SILC_LOG_DEBUG(("Client (global) %s", 
517                         silc_id_render(client->id, SILC_ID_CLIENT)));
518         if (client->router)
519           SILC_LOG_DEBUG(("Client->router (global) %s", 
520                           silc_id_render(client->router->id, SILC_ID_SERVER)));
521
522         if (client->router == from) {
523           /* Skip clients that are *really* owned by the `from' */
524           if (remove_from && SILC_ID_COMPARE(from->id, client->id, 
525                                              client->id->ip.data_len)) {
526             SILC_LOG_DEBUG(("Found really owned client, skip it"));
527             if (!silc_idcache_list_next(list, &id_cache))
528               break;
529             else
530               continue;
531           }
532
533           if (resolve_real_server) {
534             client->router = 
535               silc_server_update_clients_by_real_server(server, from, client,
536                                                         local, id_cache);
537             if (!client->router)
538               client->router = to;
539           } else {
540             client->router = to;
541           }
542         }
543
544         if (!silc_idcache_list_next(list, &id_cache))
545           break;
546       }
547     }
548     silc_idcache_list_free(list);
549   }
550
551   local = TRUE;
552   if (silc_idcache_get_all(server->local_list->clients, &list)) {
553     if (silc_idcache_list_first(list, &id_cache)) {
554       while (id_cache) {
555         client = (SilcClientEntry)id_cache->context;
556         if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
557           if (!silc_idcache_list_next(list, &id_cache))
558             break;
559           else
560             continue;
561         }
562
563         SILC_LOG_DEBUG(("Client (local) %s", 
564                         silc_id_render(client->id, SILC_ID_CLIENT)));
565         if (client->router)
566           SILC_LOG_DEBUG(("Client->router (local) %s", 
567                           silc_id_render(client->router->id, SILC_ID_SERVER)));
568
569         if (client->router == from) {
570           /* Skip clients that are *really* owned by the `from' */
571           if (remove_from && SILC_ID_COMPARE(from->id, client->id, 
572                                              client->id->ip.data_len)) {
573             SILC_LOG_DEBUG(("Found really owned client, skip it"));
574             if (!silc_idcache_list_next(list, &id_cache))
575               break;
576             else
577               continue;
578           }
579
580           if (resolve_real_server) {
581             client->router = 
582               silc_server_update_clients_by_real_server(server, from, client,
583                                                         local, id_cache);
584             if (!client->router)
585               client->router = from; /* on local list put old from */
586           } else {
587             client->router = to;
588           }
589         }
590
591         if (!silc_idcache_list_next(list, &id_cache))
592           break;
593       }
594     }
595     silc_idcache_list_free(list);
596   }
597
598   if (remove_from)
599     /* Now remove the clients that are still marked as orignated from the
600        `from'. These are the clients that really was owned by the `from' and
601        not just exist behind the `from'. */
602     silc_server_remove_clients_by_server(server, from, TRUE);
603 }
604
605 /* Updates servers that are from `from' to be originated from `to'.  This
606    will also update the server's connection to `to's connection. */
607
608 void silc_server_update_servers_by_server(SilcServer server, 
609                                           SilcServerEntry from,
610                                           SilcServerEntry to)
611 {
612   SilcIDCacheList list = NULL;
613   SilcIDCacheEntry id_cache = NULL;
614   SilcServerEntry server_entry = NULL;
615
616   SILC_LOG_DEBUG(("Start"));
617
618   if (silc_idcache_get_all(server->local_list->servers, &list)) {
619     if (silc_idcache_list_first(list, &id_cache)) {
620       while (id_cache) {
621         server_entry = (SilcServerEntry)id_cache->context;
622         if (server_entry->router == from) {
623           server_entry->router = to;
624           server_entry->connection = to->connection;
625         }
626         if (!silc_idcache_list_next(list, &id_cache))
627           break;
628       }
629     }
630     silc_idcache_list_free(list);
631   }
632
633   if (silc_idcache_get_all(server->global_list->servers, &list)) {
634     if (silc_idcache_list_first(list, &id_cache)) {
635       while (id_cache) {
636         server_entry = (SilcServerEntry)id_cache->context;
637         if (server_entry->router == from) {
638           server_entry->router = to;
639           server_entry->connection = to->connection;
640         }
641         if (!silc_idcache_list_next(list, &id_cache))
642           break;
643       }
644     }
645     silc_idcache_list_free(list);
646   }
647 }
648
649 /* Removes channels that are from `from. */
650
651 void silc_server_remove_channels_by_server(SilcServer server, 
652                                            SilcServerEntry from)
653 {
654   SilcIDCacheList list = NULL;
655   SilcIDCacheEntry id_cache = NULL;
656   SilcChannelEntry channel = NULL;
657
658   SILC_LOG_DEBUG(("Start"));
659
660   if (silc_idcache_get_all(server->global_list->channels, &list)) {
661     if (silc_idcache_list_first(list, &id_cache)) {
662       while (id_cache) {
663         channel = (SilcChannelEntry)id_cache->context;
664         if (channel->router == from)
665           silc_idlist_del_channel(server->global_list, channel);
666         if (!silc_idcache_list_next(list, &id_cache))
667           break;
668       }
669     }
670     silc_idcache_list_free(list);
671   }
672 }
673
674 /* Updates channels that are from `from' to be originated from `to'.  */
675
676 void silc_server_update_channels_by_server(SilcServer server, 
677                                            SilcServerEntry from,
678                                            SilcServerEntry to)
679 {
680   SilcIDCacheList list = NULL;
681   SilcIDCacheEntry id_cache = NULL;
682   SilcChannelEntry channel = NULL;
683
684   SILC_LOG_DEBUG(("Start"));
685
686   if (silc_idcache_get_all(server->global_list->channels, &list)) {
687     if (silc_idcache_list_first(list, &id_cache)) {
688       while (id_cache) {
689         channel = (SilcChannelEntry)id_cache->context;
690         if (channel->router == from)
691           channel->router = to;
692         if (!silc_idcache_list_next(list, &id_cache))
693           break;
694       }
695     }
696     silc_idcache_list_free(list);
697   }
698 }
699
700 /* Checks whether given channel has global users.  If it does this returns
701    TRUE and FALSE if there is only locally connected clients on the channel. */
702
703 bool silc_server_channel_has_global(SilcChannelEntry channel)
704 {
705   SilcChannelClientEntry chl;
706   SilcHashTableList htl;
707
708   silc_hash_table_list(channel->user_list, &htl);
709   while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
710     if (chl->client->router) {
711       silc_hash_table_list_reset(&htl);
712       return TRUE;
713     }
714   }
715   silc_hash_table_list_reset(&htl);
716
717   return FALSE;
718 }
719
720 /* Checks whether given channel has locally connected users.  If it does this
721    returns TRUE and FALSE if there is not one locally connected client. */
722
723 bool silc_server_channel_has_local(SilcChannelEntry channel)
724 {
725   SilcChannelClientEntry chl;
726   SilcHashTableList htl;
727
728   silc_hash_table_list(channel->user_list, &htl);
729   while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
730     if (!chl->client->router) {
731       silc_hash_table_list_reset(&htl);
732       return TRUE;
733     }
734   }
735   silc_hash_table_list_reset(&htl);
736
737   return FALSE;
738 }
739
740 /* Returns TRUE if the given client is on the channel.  FALSE if not. 
741    This works because we assure that the user list on the channel is
742    always in up to date thus we can only check the channel list from 
743    `client' which is faster than checking the user list from `channel'. */
744
745 bool silc_server_client_on_channel(SilcClientEntry client,
746                                    SilcChannelEntry channel)
747 {
748   if (!client || !channel)
749     return FALSE;
750
751   return silc_hash_table_find(client->channels, channel, NULL, NULL);
752 }
753
754 /* Checks string for bad characters and returns TRUE if they are found. */
755
756 bool silc_server_name_bad_chars(const char *name, uint32 name_len)
757 {
758   int i;
759
760   for (i = 0; i < name_len; i++) {
761     if (!isascii(name[i]))
762       return TRUE;
763     if (name[i] <= 32) return TRUE;
764     if (name[i] == ' ') return TRUE;
765     if (name[i] == '*') return TRUE;
766     if (name[i] == '?') return TRUE;
767     if (name[i] == ',') return TRUE;
768   }
769
770   return FALSE;
771 }
772
773 /* Modifies the `name' if it includes bad characters and returns new
774    allocated name that does not include bad characters. */
775
776 char *silc_server_name_modify_bad(const char *name, uint32 name_len)
777 {
778   int i;
779   char *newname = strdup(name);
780
781   for (i = 0; i < name_len; i++) {
782     if (!isascii(newname[i])) newname[i] = '_';
783     if (newname[i] <= 32) newname[i] = '_';
784     if (newname[i] == ' ') newname[i] = '_';
785     if (newname[i] == '*') newname[i] = '_';
786     if (newname[i] == '?') newname[i] = '_';
787     if (newname[i] == ',') newname[i] = '_';
788   }
789
790   return newname;
791 }
792
793 /* Find number of sockets by IP address indicated by `ip'. Returns 0 if
794    socket connections with the IP address does not exist. */
795
796 uint32 silc_server_num_sockets_by_ip(SilcServer server, const char *ip)
797 {
798   int i, count;
799
800   for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
801     if (server->sockets[i] && !strcmp(server->sockets[i]->ip, ip))
802       count++;
803   }
804
805   return count;
806 }