Started implementing protocol version 1.1 and narrowing down
[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 /* 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   SilcUInt32 clients_c = 0;
148   unsigned char **argv = NULL;
149   SilcUInt32 *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                                    SilcChannelClientEntry *chl)
748 {
749   if (!client || !channel)
750     return FALSE;
751
752   return silc_hash_table_find(client->channels, channel, NULL, 
753                               (void **)chl);
754 }
755
756 /* Checks string for bad characters and returns TRUE if they are found. */
757
758 bool silc_server_name_bad_chars(const char *name, SilcUInt32 name_len)
759 {
760   int i;
761
762   for (i = 0; i < name_len; i++) {
763     if (!isascii(name[i]))
764       return TRUE;
765     if (name[i] <= 32) return TRUE;
766     if (name[i] == ' ') return TRUE;
767     if (name[i] == '*') return TRUE;
768     if (name[i] == '?') return TRUE;
769     if (name[i] == ',') return TRUE;
770   }
771
772   return FALSE;
773 }
774
775 /* Modifies the `name' if it includes bad characters and returns new
776    allocated name that does not include bad characters. */
777
778 char *silc_server_name_modify_bad(const char *name, SilcUInt32 name_len)
779 {
780   int i;
781   char *newname = strdup(name);
782
783   for (i = 0; i < name_len; i++) {
784     if (!isascii(newname[i])) newname[i] = '_';
785     if (newname[i] <= 32) newname[i] = '_';
786     if (newname[i] == ' ') newname[i] = '_';
787     if (newname[i] == '*') newname[i] = '_';
788     if (newname[i] == '?') newname[i] = '_';
789     if (newname[i] == ',') newname[i] = '_';
790   }
791
792   return newname;
793 }
794
795 /* Find number of sockets by IP address indicated by `ip'. Returns 0 if
796    socket connections with the IP address does not exist. */
797
798 SilcUInt32 silc_server_num_sockets_by_ip(SilcServer server, const char *ip,
799                                          SilcSocketType type)
800 {
801   int i, count;
802
803   for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
804     if (server->sockets[i] && !strcmp(server->sockets[i]->ip, ip) &&
805         server->sockets[i]->type == type)
806       count++;
807   }
808
809   return count;
810 }
811
812 /* Find number of sockets by IP address indicated by remote host, indicatd
813    by `ip' or `hostname', `port', and `type'.  Returns 0 if socket connections
814    does not exist. If `ip' is provided then `hostname' is ignored. */
815
816 SilcUInt32 silc_server_num_sockets_by_remote(SilcServer server, 
817                                              const char *ip,
818                                              const char *hostname,
819                                              SilcUInt16 port,
820                                              SilcSocketType type)
821 {
822   int i, count;
823
824   if (!ip && !hostname)
825     return 0;
826
827   for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
828     if (server->sockets[i] && 
829         ((ip && !strcmp(server->sockets[i]->ip, ip)) ||
830          (hostname && !strcmp(server->sockets[i]->hostname, hostname))) &&
831         server->sockets[i]->port == port &&
832         server->sockets[i]->type == type)
833       count++;
834   }
835
836   return count;
837 }
838
839 /* Finds locally cached public key by the public key received in the SKE. 
840    If we have it locally cached then we trust it and will use it in the
841    authentication protocol.  Returns the locally cached public key or NULL
842    if we do not find the public key.  */
843
844 SilcPublicKey silc_server_find_public_key(SilcServer server, 
845                                           SilcHashTable local_public_keys,
846                                           SilcPublicKey remote_public_key)
847 {
848   SilcPublicKey cached_key;
849
850   SILC_LOG_DEBUG(("Find remote public key (%d keys in local cache)",
851                   silc_hash_table_count(local_public_keys)));
852
853   if (!silc_hash_table_find_ext(local_public_keys, remote_public_key,
854                                 (void **)&cached_key, NULL, 
855                                 silc_hash_public_key, NULL,
856                                 silc_hash_public_key_compare, NULL)) {
857     SILC_LOG_ERROR(("Public key not found"));
858     return NULL;
859   }
860
861   SILC_LOG_DEBUG(("Found public key"));
862
863   return cached_key;
864 }
865
866 /* This returns the first public key from the table of public keys.  This
867    is used only in cases where single public key exists in the table and
868    we want to get a pointer to it.  For public key tables that has multiple
869    keys in it the silc_server_find_public_key must be used. */
870
871 SilcPublicKey silc_server_get_public_key(SilcServer server,
872                                          SilcHashTable local_public_keys)
873 {
874   SilcPublicKey cached_key;
875   SilcHashTableList htl;
876
877   SILC_LOG_DEBUG(("Start"));
878
879   assert(silc_hash_table_count(local_public_keys) < 2);
880
881   silc_hash_table_list(local_public_keys, &htl);
882   if (!silc_hash_table_get(&htl, NULL, (void **)&cached_key))
883     return NULL;
884   silc_hash_table_list_reset(&htl);
885
886   return cached_key;
887 }
888
889 /* Check whether the connection `sock' is allowed to connect to us.  This
890    checks for example whether there is too much connections for this host,
891    and required version for the host etc. */
892
893 bool silc_server_connection_allowed(SilcServer server, 
894                                     SilcSocketConnection sock,
895                                     SilcSocketType type,
896                                     SilcServerConfigConnParams *global,
897                                     SilcServerConfigConnParams *params,
898                                     SilcSKE ske)
899 {
900   SilcUInt32 conn_number = (type == SILC_SOCKET_TYPE_CLIENT ?
901                             server->stat.my_clients :
902                             type == SILC_SOCKET_TYPE_SERVER ?
903                             server->stat.my_servers :
904                             server->stat.my_routers);
905   SilcUInt32 num_sockets, max_hosts, max_per_host;
906   SilcUInt32 r_protocol_version, l_protocol_version;
907   SilcUInt32 r_software_version, l_software_version;
908   char *r_vendor_version = NULL, *l_vendor_version;
909
910   /* Check version */
911
912   l_protocol_version = 
913     silc_version_to_num(params && params->version_protocol ? 
914                         params->version_protocol : 
915                         global->version_protocol);
916   l_software_version = 
917     silc_version_to_num(params && params->version_software ? 
918                         params->version_software : 
919                         global->version_software);
920   l_vendor_version = (params && params->version_software_vendor ? 
921                       params->version_software_vendor : 
922                       global->version_software_vendor);
923   
924   if (ske && silc_ske_parse_version(ske, &r_protocol_version, NULL,
925                                     &r_software_version, NULL,
926                                     &r_vendor_version)) {
927     sock->version = r_protocol_version;
928
929     /* Match protocol version */
930     if (l_protocol_version && r_protocol_version &&
931         r_protocol_version < l_protocol_version) {
932       SILC_LOG_INFO(("Connection %s (%s) is too old version",
933                      sock->hostname, sock->ip));
934       silc_server_disconnect_remote(server, sock, 
935                                     "Server closed connection: "
936                                     "You support too old protocol version");
937       return FALSE;
938     }
939
940     /* Math software version */
941     if (l_software_version && r_software_version &&
942         r_software_version < l_software_version) {
943       SILC_LOG_INFO(("Connection %s (%s) is too old version",
944                      sock->hostname, sock->ip));
945       silc_server_disconnect_remote(server, sock, 
946                                     "Server closed connection: "
947                                     "You support too old software version");
948       return FALSE;
949     }
950
951     /* Regex match vendor version */
952     if (l_vendor_version && r_vendor_version && 
953         !silc_string_match(l_vendor_version, r_vendor_version)) {
954       SILC_LOG_INFO(("Connection %s (%s) is unsupported version",
955                      sock->hostname, sock->ip));
956       silc_server_disconnect_remote(server, sock, 
957                                     "Server closed connection: "
958                                     "Your software is not supported");
959       return FALSE;
960     }
961   }
962   silc_free(r_vendor_version);
963
964   /* Check for maximum connections limit */
965
966   num_sockets = silc_server_num_sockets_by_ip(server, sock->ip, type);
967   max_hosts = (params ? params->connections_max : global->connections_max);
968   max_per_host = (params ? params->connections_max_per_host :
969                   global->connections_max_per_host);
970
971   if (max_hosts && conn_number >= max_hosts) {
972     SILC_LOG_INFO(("Server is full, closing %s (%s) connection",
973                    sock->hostname, sock->ip));
974     silc_server_disconnect_remote(server, sock, 
975                                   "Server closed connection: "
976                                   "Server is full, try again later");
977     return FALSE;
978   }
979
980   if (num_sockets >= max_per_host) {
981     SILC_LOG_INFO(("Too many connections from %s (%s), closing connection",
982                    sock->hostname, sock->ip));
983     silc_server_disconnect_remote(server, sock, 
984                                   "Server closed connection: "
985                                   "Too many connections from your host");
986     return FALSE;
987   }
988
989   return TRUE;
990 }
991
992 /* Checks that client has rights to add or remove channel modes. If any
993    of the checks fails FALSE is returned. */
994
995 bool silc_server_check_cmode_rights(SilcServer server,
996                                     SilcChannelEntry channel,
997                                     SilcChannelClientEntry client,
998                                     SilcUInt32 mode)
999 {
1000   bool is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1001   bool is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1002
1003   /* Check whether has rights to change anything */
1004   if (!is_op && !is_fo)
1005     return FALSE;
1006
1007   /* Check whether has rights to change everything */
1008   if (is_op && is_fo)
1009     return TRUE;
1010
1011   /* We know that client is channel operator, check that they are not
1012      changing anything that requires channel founder rights. Rest of the
1013      modes are available automatically for channel operator. */
1014
1015   if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1016     if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
1017       if (is_op && !is_fo)
1018         return FALSE;
1019   } else {
1020     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1021       if (is_op && !is_fo)
1022         return FALSE;
1023     }
1024   }
1025   
1026   if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1027     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
1028       if (is_op && !is_fo)
1029         return FALSE;
1030   } else {
1031     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1032       if (is_op && !is_fo)
1033         return FALSE;
1034     }
1035   }
1036
1037   if (mode & SILC_CHANNEL_MODE_CIPHER) {
1038     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
1039       if (is_op && !is_fo)
1040         return FALSE;
1041   } else {
1042     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1043       if (is_op && !is_fo)
1044         return FALSE;
1045     }
1046   }
1047   
1048   if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1049     if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
1050       if (is_op && !is_fo)
1051         return FALSE;
1052   } else {
1053     if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1054       if (is_op && !is_fo)
1055         return FALSE;
1056     }
1057   }
1058   
1059   if (mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1060     if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS))
1061       if (is_op && !is_fo)
1062         return FALSE;
1063   } else {
1064     if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1065       if (is_op && !is_fo)
1066         return FALSE;
1067     }
1068   }
1069   
1070   if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1071     if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS))
1072       if (is_op && !is_fo)
1073         return FALSE;
1074   } else {
1075     if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1076       if (is_op && !is_fo)
1077         return FALSE;
1078     }
1079   }
1080   
1081   return TRUE;
1082 }
1083
1084 /* Check that the client has rights to change its user mode.  Returns
1085    FALSE if setting some mode is not allowed. */
1086
1087 bool silc_server_check_umode_rights(SilcServer server,
1088                                     SilcClientEntry client,
1089                                     SilcUInt32 mode)
1090 {
1091   bool server_op = FALSE, router_op = FALSE;
1092
1093   if (mode & SILC_UMODE_SERVER_OPERATOR) {
1094     /* Cannot set server operator mode (must use OPER command) */
1095     if (!(client->mode & SILC_UMODE_SERVER_OPERATOR))
1096       return FALSE;
1097   } else {
1098     /* Remove the server operator rights */
1099     if (client->mode & SILC_UMODE_SERVER_OPERATOR)
1100       server_op = TRUE;
1101   }
1102
1103   if (mode & SILC_UMODE_ROUTER_OPERATOR) {
1104     /* Cannot set router operator mode (must use SILCOPER command) */
1105     if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR))
1106       return FALSE;
1107   } else {
1108     /* Remove the router operator rights */
1109     if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
1110       router_op = TRUE;
1111   }
1112
1113   if (server_op)
1114     SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR);
1115   if (router_op)
1116     SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR);
1117
1118   return TRUE;
1119 }