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 - 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 silc_server_remove_clients_channels(SilcServer server, 
32                                                 SilcSocketConnection sock,
33                                                 SilcClientEntry client,
34                                                 SilcHashTable channels)
35 {
36   SilcChannelEntry channel;
37   SilcChannelClientEntry chl;
38   SilcHashTableList htl;
39   SilcBuffer clidp;
40
41   SILC_LOG_DEBUG(("Start"));
42
43   if (!client || !client->id)
44     return;
45
46   clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
47
48   /* Remove the client from all channels. The client is removed from
49      the channels' user list. */
50   silc_hash_table_list(client->channels, &htl);
51   while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
52     channel = chl->channel;
53
54     /* Remove channel from client's channel list */
55     silc_hash_table_del(client->channels, channel);
56
57     /* Remove channel if there is no users anymore */
58     if (server->server_type == SILC_ROUTER &&
59         silc_hash_table_count(channel->user_list) < 2) {
60
61       if (silc_hash_table_find(channels, channel, NULL, NULL))
62         silc_hash_table_del(channels, channel);
63
64       if (channel->rekey)
65         silc_schedule_task_del_by_context(server->schedule, channel->rekey);
66
67       if (silc_idlist_del_channel(server->local_list, channel))
68         server->stat.my_channels--;
69       else 
70         silc_idlist_del_channel(server->global_list, channel);
71       continue;
72     }
73
74     /* Remove client from channel's client list */
75     silc_hash_table_del(channel->user_list, chl->client);
76     channel->user_count--;
77
78     /* If there is no global users on the channel anymore mark the channel
79        as local channel. Do not check if the removed client is local client. */
80     if (server->server_type != SILC_ROUTER && channel->global_users && 
81         chl->client->router && !silc_server_channel_has_global(channel))
82       channel->global_users = FALSE;
83
84     silc_free(chl);
85     server->stat.my_chanclients--;
86
87     /* If there is not at least one local user on the channel then we don't
88        need the channel entry anymore, we can remove it safely. */
89     if (server->server_type != SILC_ROUTER &&
90         !silc_server_channel_has_local(channel)) {
91
92       if (silc_hash_table_find(channels, channel, NULL, NULL))
93         silc_hash_table_del(channels, channel);
94
95       if (channel->rekey)
96         silc_schedule_task_del_by_context(server->schedule, channel->rekey);
97
98       if (channel->founder_key) {
99         /* The founder auth data exists, do not remove the channel entry */
100         SilcChannelClientEntry chl2;
101         SilcHashTableList htl2;
102
103         channel->disabled = TRUE;
104
105         silc_hash_table_list(channel->user_list, &htl2);
106         while (silc_hash_table_get(&htl2, NULL, (void **)&chl2)) {
107           silc_hash_table_del(chl2->client->channels, channel);
108           silc_hash_table_del(channel->user_list, chl2->client);
109           channel->user_count--;
110           silc_free(chl2);
111         }
112         silc_hash_table_list_reset(&htl2);
113         continue;
114       }
115
116       /* Remove the channel entry */
117       if (silc_idlist_del_channel(server->local_list, channel))
118         server->stat.my_channels--;
119       else 
120         silc_idlist_del_channel(server->global_list, channel);
121       continue;
122     }
123
124     /* Add the channel to the the channels list to regenerate the 
125        channel key */
126     if (!silc_hash_table_find(channels, channel, NULL, NULL))
127       silc_hash_table_add(channels, channel, channel);
128   }
129   silc_hash_table_list_reset(&htl);
130
131   silc_buffer_free(clidp);
132 }
133
134 /* This function is used to remove all client entries by the server `entry'.
135    This is called when the connection is lost to the server. In this case
136    we must invalidate all the client entries owned by the server `entry'. 
137    If the `server_signoff' is TRUE then the SERVER_SIGNOFF notify is
138    distributed to our local clients. */
139
140 bool silc_server_remove_clients_by_server(SilcServer server, 
141                                           SilcServerEntry entry,
142                                           bool server_signoff)
143 {
144   SilcIDCacheList list = NULL;
145   SilcIDCacheEntry id_cache = NULL;
146   SilcClientEntry client = NULL;
147   SilcBuffer idp;
148   SilcClientEntry *clients = NULL;
149   SilcUInt32 clients_c = 0;
150   unsigned char **argv = NULL;
151   SilcUInt32 *argv_lens = NULL, *argv_types = NULL, argc = 0;
152   SilcHashTableList htl;
153   SilcChannelEntry channel;
154   SilcHashTable channels;
155   int i;
156
157   SILC_LOG_DEBUG(("Start"));
158
159   /* Allocate the hash table that holds the channels that require
160      channel key re-generation after we've removed this server's clients
161      from the channels. */
162   channels = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL,
163                                    NULL, NULL, TRUE);
164
165   if (server_signoff) {
166     idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
167     argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
168     argv_lens = silc_realloc(argv_lens,  sizeof(*argv_lens) * (argc + 1));
169     argv_types = silc_realloc(argv_types, sizeof(*argv_types) * (argc + 1));
170     argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
171     memcpy(argv[argc], idp->data, idp->len);
172     argv_lens[argc] = idp->len;
173     argv_types[argc] = argc + 1;
174     argc++;
175     silc_buffer_free(idp);
176   }
177
178   if (silc_idcache_get_all(server->local_list->clients, &list)) {
179
180     if (silc_idcache_list_first(list, &id_cache)) {
181       while (id_cache) {
182         client = (SilcClientEntry)id_cache->context;
183         if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
184           if (!silc_idcache_list_next(list, &id_cache))
185             break;
186           else
187             continue;
188         }
189
190         if (client->router != entry) {
191           if (server_signoff) {
192             clients = silc_realloc(clients, 
193                                    sizeof(*clients) * (clients_c + 1));
194             clients[clients_c] = client;
195             clients_c++;
196           }
197
198           if (!silc_idcache_list_next(list, &id_cache))
199             break;
200           else
201             continue;
202         }
203
204         if (server_signoff) {
205           idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
206           argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
207           argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
208                                    (argc + 1));
209           argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
210                                     (argc + 1));
211           argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
212           memcpy(argv[argc], idp->data, idp->len);
213           argv_lens[argc] = idp->len;
214           argv_types[argc] = argc + 1;
215           argc++;
216           silc_buffer_free(idp);
217         }
218
219         /* Update statistics */
220         server->stat.clients--;
221         if (server->stat.cell_clients)
222           server->stat.cell_clients--;
223         SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
224         SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
225
226         /* Remove the client entry */
227         silc_server_remove_clients_channels(server, NULL, client, channels);
228         if (!server_signoff) {
229           client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
230           id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
231         } else {
232           silc_idlist_del_client(server->local_list, client);
233         }
234
235         if (!silc_idcache_list_next(list, &id_cache))
236           break;
237       }
238     }
239     silc_idcache_list_free(list);
240   }
241   
242   if (silc_idcache_get_all(server->global_list->clients, &list)) {
243
244     if (silc_idcache_list_first(list, &id_cache)) {
245       while (id_cache) {
246         client = (SilcClientEntry)id_cache->context;
247         if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
248           if (!silc_idcache_list_next(list, &id_cache))
249             break;
250           else
251             continue;
252         }
253         
254         if (client->router != entry) {
255           if (server_signoff && client->connection) {
256             clients = silc_realloc(clients, 
257                                    sizeof(*clients) * (clients_c + 1));
258             clients[clients_c] = client;
259             clients_c++;
260           }
261
262           if (!silc_idcache_list_next(list, &id_cache))
263             break;
264           else
265             continue;
266         }
267
268         if (server_signoff) {
269           idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
270           argv = silc_realloc(argv, sizeof(*argv) * (argc + 1));
271           argv_lens = silc_realloc(argv_lens, sizeof(*argv_lens) *
272                                    (argc + 1));
273           argv_types = silc_realloc(argv_types, sizeof(*argv_types) *
274                                     (argc + 1));
275           argv[argc] = silc_calloc(idp->len, sizeof(*argv[0]));
276           memcpy(argv[argc], idp->data, idp->len);
277           argv_lens[argc] = idp->len;
278           argv_types[argc] = argc + 1;
279           argc++;
280           silc_buffer_free(idp);
281         }
282
283         /* Update statistics */
284         server->stat.clients--;
285         if (server->stat.cell_clients)
286           server->stat.cell_clients--;
287         SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
288         SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
289
290         /* Remove the client entry */
291         silc_server_remove_clients_channels(server, NULL, client, channels);
292         if (!server_signoff) {
293           client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
294           id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
295         } else {
296           silc_idlist_del_client(server->global_list, client);
297         }
298
299         if (!silc_idcache_list_next(list, &id_cache))
300           break;
301       }
302     }
303     silc_idcache_list_free(list);
304   }
305
306   /* Send the SERVER_SIGNOFF notify */
307   if (server_signoff) {
308     SilcBuffer args, not;
309
310     /* Send SERVER_SIGNOFF notify to our primary router */
311     if (!server->standalone && server->router &&
312         server->router != entry) {
313       args = silc_argument_payload_encode(1, argv, argv_lens,
314                                           argv_types);
315       silc_server_send_notify_args(server, 
316                                    server->router->connection,
317                                    server->server_type == SILC_SERVER ? 
318                                    FALSE : TRUE, 
319                                    SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
320                                    argc, args);
321       silc_buffer_free(args);
322     }
323
324     /* Send to local clients. We also send the list of client ID's that
325        is to be removed for those servers that would like to use that list. */
326     args = silc_argument_payload_encode(argc, argv, argv_lens,
327                                         argv_types);
328     not = silc_notify_payload_encode_args(SILC_NOTIFY_TYPE_SERVER_SIGNOFF, 
329                                           argc, args);
330     silc_server_packet_send_clients(server, clients, clients_c,
331                                     SILC_PACKET_NOTIFY, 0, FALSE,
332                                     not->data, not->len, FALSE);
333
334     silc_free(clients);
335     silc_buffer_free(args);
336     silc_buffer_free(not);
337     for (i = 0; i < argc; i++)
338       silc_free(argv[i]);
339     silc_free(argv);
340     silc_free(argv_lens);
341     silc_free(argv_types);
342   }
343
344   /* We must now re-generate the channel key for all channels that had
345      this server's client(s) on the channel. As they left the channel we
346      must re-generate the channel key. */
347   silc_hash_table_list(channels, &htl);
348   while (silc_hash_table_get(&htl, NULL, (void **)&channel)) {
349     if (!silc_server_create_channel_key(server, channel, 0)) {
350       silc_hash_table_list_reset(&htl);
351       silc_hash_table_free(channels);
352       return FALSE;
353     }
354
355     /* Do not send the channel key if private channel key mode is set */
356     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY)
357       continue;
358
359     silc_server_send_channel_key(server, NULL, channel, 
360                                  server->server_type == SILC_ROUTER ? 
361                                  FALSE : !server->standalone);
362   }
363   silc_hash_table_list_reset(&htl);
364   silc_hash_table_free(channels);
365
366   return TRUE;
367 }
368
369 static SilcServerEntry
370 silc_server_update_clients_by_real_server(SilcServer server,
371                                           SilcServerEntry from,
372                                           SilcClientEntry client,
373                                           bool local,
374                                           SilcIDCacheEntry client_cache)
375 {
376   SilcServerEntry server_entry;
377   SilcIDCacheEntry id_cache = NULL;
378   SilcIDCacheList list;
379
380   if (!silc_idcache_get_all(server->local_list->servers, &list))
381     return NULL;
382
383   if (silc_idcache_list_first(list, &id_cache)) {
384     while (id_cache) {
385       server_entry = (SilcServerEntry)id_cache->context;
386       if (server_entry != from &&
387           SILC_ID_COMPARE(server_entry->id, client->id, 
388                           client->id->ip.data_len)) {
389         SILC_LOG_DEBUG(("Found (local) %s",
390                         silc_id_render(server_entry->id, SILC_ID_SERVER)));
391
392         if (!server_entry->data.send_key && server_entry->router) {
393           SILC_LOG_DEBUG(("Server not locally connected, use its router"));
394           /* If the client is not marked as local then move it to local list
395              since the server is local. */
396           if (!local) {
397             SILC_LOG_DEBUG(("Moving client to local list"));
398             silc_idcache_add(server->local_list->clients, client_cache->name,
399                              client_cache->id, client_cache->context,
400                              client_cache->expire, NULL);
401             silc_idcache_del_by_context(server->global_list->clients, client);
402           }
403           server_entry = server_entry->router;
404         } else {
405           /* If the client is not marked as local then move it to local list
406              since the server is local. */
407           if (server_entry->server_type != SILC_BACKUP_ROUTER && !local) {
408             SILC_LOG_DEBUG(("Moving client to local list"));
409             silc_idcache_add(server->local_list->clients, client_cache->name,
410                              client_cache->id, client_cache->context,
411                              client_cache->expire, NULL);
412             silc_idcache_del_by_context(server->global_list->clients, client);
413           }
414         }
415
416         silc_idcache_list_free(list);
417         return server_entry;
418       }
419
420       if (!silc_idcache_list_next(list, &id_cache))
421         break;
422     }
423   }
424
425   silc_idcache_list_free(list);
426
427   if (!silc_idcache_get_all(server->global_list->servers, &list))
428     return NULL;
429
430   if (silc_idcache_list_first(list, &id_cache)) {
431     while (id_cache) {
432       server_entry = (SilcServerEntry)id_cache->context;
433       if (server_entry != from &&
434           SILC_ID_COMPARE(server_entry->id, client->id, 
435                           client->id->ip.data_len)) {
436         SILC_LOG_DEBUG(("Found (global) %s",
437                         silc_id_render(server_entry->id, SILC_ID_SERVER)));
438
439         if (!server_entry->data.send_key && server_entry->router) {
440           SILC_LOG_DEBUG(("Server not locally connected, use its router"));
441           /* If the client is marked as local then move it to global list
442              since the server is global. */
443           if (local) {
444             SILC_LOG_DEBUG(("Moving client to global list"));
445             silc_idcache_add(server->global_list->clients, client_cache->name,
446                              client_cache->id, client_cache->context,
447                              client_cache->expire, NULL);
448             silc_idcache_del_by_context(server->local_list->clients, client);
449           }
450           server_entry = server_entry->router;
451         } else {
452           /* If the client is marked as local then move it to global list
453              since the server is global. */
454           if (server_entry->server_type != SILC_BACKUP_ROUTER && local) {
455             SILC_LOG_DEBUG(("Moving client to global list"));
456             silc_idcache_add(server->global_list->clients, client_cache->name,
457                              client_cache->id, client_cache->context,
458                              client_cache->expire, NULL);
459             silc_idcache_del_by_context(server->local_list->clients, client);
460           }
461         }
462
463         silc_idcache_list_free(list);
464         return server_entry;
465       }
466
467       if (!silc_idcache_list_next(list, &id_cache))
468         break;
469     }
470   }
471
472   silc_idcache_list_free(list);
473
474   return NULL;
475 }
476
477 /* Updates the clients that are originated from the `from' to be originated
478    from the `to'. If the `resolve_real_server' is TRUE then this will
479    attempt to figure out which clients really are originated from the
480    `from' and which are originated from a server that we have connection
481    to, when we've acting as backup router. If it is FALSE the `to' will
482    be the new source. This function also removes the clients that are
483    *really* originated from `from' if `remove_from' is TRUE. These are
484    clients that the `from' owns, and not just clients that are behind
485    the `from'. */
486
487 void silc_server_update_clients_by_server(SilcServer server, 
488                                           SilcServerEntry from,
489                                           SilcServerEntry to,
490                                           bool resolve_real_server,
491                                           bool remove_from)
492 {
493   SilcIDCacheList list = NULL;
494   SilcIDCacheEntry id_cache = NULL;
495   SilcClientEntry client = NULL;
496   bool local;
497
498   SILC_LOG_DEBUG(("Start"));
499
500   SILC_LOG_DEBUG(("Updating %s", silc_id_render(from->id,
501                                                 SILC_ID_SERVER)));
502   SILC_LOG_DEBUG(("to %s", silc_id_render(to->id,
503                                           SILC_ID_SERVER)));
504
505
506   local = FALSE;
507   if (silc_idcache_get_all(server->global_list->clients, &list)) {
508     if (silc_idcache_list_first(list, &id_cache)) {
509       while (id_cache) {
510         client = (SilcClientEntry)id_cache->context;
511         if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
512           if (!silc_idcache_list_next(list, &id_cache))
513             break;
514           else
515             continue;
516         }
517
518         SILC_LOG_DEBUG(("Client (global) %s", 
519                         silc_id_render(client->id, SILC_ID_CLIENT)));
520         if (client->router)
521           SILC_LOG_DEBUG(("Client->router (global) %s", 
522                           silc_id_render(client->router->id, SILC_ID_SERVER)));
523
524         if (client->router == from) {
525           /* Skip clients that are *really* owned by the `from' */
526           if (remove_from && SILC_ID_COMPARE(from->id, client->id, 
527                                              client->id->ip.data_len)) {
528             SILC_LOG_DEBUG(("Found really owned client, skip it"));
529             if (!silc_idcache_list_next(list, &id_cache))
530               break;
531             else
532               continue;
533           }
534
535           if (resolve_real_server) {
536             client->router = 
537               silc_server_update_clients_by_real_server(server, from, client,
538                                                         local, id_cache);
539             if (!client->router)
540               client->router = to;
541           } else {
542             client->router = to;
543           }
544         }
545
546         if (!silc_idcache_list_next(list, &id_cache))
547           break;
548       }
549     }
550     silc_idcache_list_free(list);
551   }
552
553   local = TRUE;
554   if (silc_idcache_get_all(server->local_list->clients, &list)) {
555     if (silc_idcache_list_first(list, &id_cache)) {
556       while (id_cache) {
557         client = (SilcClientEntry)id_cache->context;
558         if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
559           if (!silc_idcache_list_next(list, &id_cache))
560             break;
561           else
562             continue;
563         }
564
565         SILC_LOG_DEBUG(("Client (local) %s", 
566                         silc_id_render(client->id, SILC_ID_CLIENT)));
567         if (client->router)
568           SILC_LOG_DEBUG(("Client->router (local) %s", 
569                           silc_id_render(client->router->id, SILC_ID_SERVER)));
570
571         if (client->router == from) {
572           /* Skip clients that are *really* owned by the `from' */
573           if (remove_from && SILC_ID_COMPARE(from->id, client->id, 
574                                              client->id->ip.data_len)) {
575             SILC_LOG_DEBUG(("Found really owned client, skip it"));
576             if (!silc_idcache_list_next(list, &id_cache))
577               break;
578             else
579               continue;
580           }
581
582           if (resolve_real_server) {
583             client->router = 
584               silc_server_update_clients_by_real_server(server, from, client,
585                                                         local, id_cache);
586             if (!client->router)
587               client->router = from; /* on local list put old from */
588           } else {
589             client->router = to;
590           }
591         }
592
593         if (!silc_idcache_list_next(list, &id_cache))
594           break;
595       }
596     }
597     silc_idcache_list_free(list);
598   }
599
600   if (remove_from)
601     /* Now remove the clients that are still marked as orignated from the
602        `from'. These are the clients that really was owned by the `from' and
603        not just exist behind the `from'. */
604     silc_server_remove_clients_by_server(server, from, TRUE);
605 }
606
607 /* Updates servers that are from `from' to be originated from `to'.  This
608    will also update the server's connection to `to's connection. */
609
610 void silc_server_update_servers_by_server(SilcServer server, 
611                                           SilcServerEntry from,
612                                           SilcServerEntry to)
613 {
614   SilcIDCacheList list = NULL;
615   SilcIDCacheEntry id_cache = NULL;
616   SilcServerEntry server_entry = NULL;
617
618   SILC_LOG_DEBUG(("Start"));
619
620   if (silc_idcache_get_all(server->local_list->servers, &list)) {
621     if (silc_idcache_list_first(list, &id_cache)) {
622       while (id_cache) {
623         server_entry = (SilcServerEntry)id_cache->context;
624         if (server_entry->router == from) {
625           server_entry->router = to;
626           server_entry->connection = to->connection;
627         }
628         if (!silc_idcache_list_next(list, &id_cache))
629           break;
630       }
631     }
632     silc_idcache_list_free(list);
633   }
634
635   if (silc_idcache_get_all(server->global_list->servers, &list)) {
636     if (silc_idcache_list_first(list, &id_cache)) {
637       while (id_cache) {
638         server_entry = (SilcServerEntry)id_cache->context;
639         if (server_entry->router == from) {
640           server_entry->router = to;
641           server_entry->connection = to->connection;
642         }
643         if (!silc_idcache_list_next(list, &id_cache))
644           break;
645       }
646     }
647     silc_idcache_list_free(list);
648   }
649 }
650
651 /* Removes channels that are from `from. */
652
653 void silc_server_remove_channels_by_server(SilcServer server, 
654                                            SilcServerEntry from)
655 {
656   SilcIDCacheList list = NULL;
657   SilcIDCacheEntry id_cache = NULL;
658   SilcChannelEntry channel = NULL;
659
660   SILC_LOG_DEBUG(("Start"));
661
662   if (silc_idcache_get_all(server->global_list->channels, &list)) {
663     if (silc_idcache_list_first(list, &id_cache)) {
664       while (id_cache) {
665         channel = (SilcChannelEntry)id_cache->context;
666         if (channel->router == from)
667           silc_idlist_del_channel(server->global_list, channel);
668         if (!silc_idcache_list_next(list, &id_cache))
669           break;
670       }
671     }
672     silc_idcache_list_free(list);
673   }
674 }
675
676 /* Updates channels that are from `from' to be originated from `to'.  */
677
678 void silc_server_update_channels_by_server(SilcServer server, 
679                                            SilcServerEntry from,
680                                            SilcServerEntry to)
681 {
682   SilcIDCacheList list = NULL;
683   SilcIDCacheEntry id_cache = NULL;
684   SilcChannelEntry channel = NULL;
685
686   SILC_LOG_DEBUG(("Start"));
687
688   if (silc_idcache_get_all(server->global_list->channels, &list)) {
689     if (silc_idcache_list_first(list, &id_cache)) {
690       while (id_cache) {
691         channel = (SilcChannelEntry)id_cache->context;
692         if (channel->router == from)
693           channel->router = to;
694         if (!silc_idcache_list_next(list, &id_cache))
695           break;
696       }
697     }
698     silc_idcache_list_free(list);
699   }
700 }
701
702 /* Checks whether given channel has global users.  If it does this returns
703    TRUE and FALSE if there is only locally connected clients on the channel. */
704
705 bool silc_server_channel_has_global(SilcChannelEntry channel)
706 {
707   SilcChannelClientEntry chl;
708   SilcHashTableList htl;
709
710   silc_hash_table_list(channel->user_list, &htl);
711   while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
712     if (chl->client->router) {
713       silc_hash_table_list_reset(&htl);
714       return TRUE;
715     }
716   }
717   silc_hash_table_list_reset(&htl);
718
719   return FALSE;
720 }
721
722 /* Checks whether given channel has locally connected users.  If it does this
723    returns TRUE and FALSE if there is not one locally connected client. */
724
725 bool silc_server_channel_has_local(SilcChannelEntry channel)
726 {
727   SilcChannelClientEntry chl;
728   SilcHashTableList htl;
729
730   silc_hash_table_list(channel->user_list, &htl);
731   while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
732     if (!chl->client->router) {
733       silc_hash_table_list_reset(&htl);
734       return TRUE;
735     }
736   }
737   silc_hash_table_list_reset(&htl);
738
739   return FALSE;
740 }
741
742 /* Returns TRUE if the given client is on the channel.  FALSE if not. 
743    This works because we assure that the user list on the channel is
744    always in up to date thus we can only check the channel list from 
745    `client' which is faster than checking the user list from `channel'. */
746
747 bool silc_server_client_on_channel(SilcClientEntry client,
748                                    SilcChannelEntry channel,
749                                    SilcChannelClientEntry *chl)
750 {
751   if (!client || !channel)
752     return FALSE;
753
754   return silc_hash_table_find(client->channels, channel, NULL, 
755                               (void **)chl);
756 }
757
758 /* Checks string for bad characters and returns TRUE if they are found. */
759
760 bool silc_server_name_bad_chars(const char *name, SilcUInt32 name_len)
761 {
762   int i;
763
764   for (i = 0; i < name_len; i++) {
765     if (!isascii(name[i]))
766       return TRUE;
767     if (name[i] <= 32) return TRUE;
768     if (name[i] == ' ') return TRUE;
769     if (name[i] == '*') return TRUE;
770     if (name[i] == '?') return TRUE;
771     if (name[i] == ',') return TRUE;
772   }
773
774   return FALSE;
775 }
776
777 /* Modifies the `name' if it includes bad characters and returns new
778    allocated name that does not include bad characters. */
779
780 char *silc_server_name_modify_bad(const char *name, SilcUInt32 name_len)
781 {
782   int i;
783   char *newname = strdup(name);
784
785   for (i = 0; i < name_len; i++) {
786     if (!isascii(newname[i])) newname[i] = '_';
787     if (newname[i] <= 32) newname[i] = '_';
788     if (newname[i] == ' ') newname[i] = '_';
789     if (newname[i] == '*') newname[i] = '_';
790     if (newname[i] == '?') newname[i] = '_';
791     if (newname[i] == ',') newname[i] = '_';
792   }
793
794   return newname;
795 }
796
797 /* Find number of sockets by IP address indicated by `ip'. Returns 0 if
798    socket connections with the IP address does not exist. */
799
800 SilcUInt32 silc_server_num_sockets_by_ip(SilcServer server, const char *ip,
801                                          SilcSocketType type)
802 {
803   int i, count;
804
805   for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
806     if (server->sockets[i] && !strcmp(server->sockets[i]->ip, ip) &&
807         server->sockets[i]->type == type)
808       count++;
809   }
810
811   return count;
812 }
813
814 /* Find number of sockets by IP address indicated by remote host, indicatd
815    by `ip' or `hostname', `port', and `type'.  Returns 0 if socket connections
816    does not exist. If `ip' is provided then `hostname' is ignored. */
817
818 SilcUInt32 silc_server_num_sockets_by_remote(SilcServer server, 
819                                              const char *ip,
820                                              const char *hostname,
821                                              SilcUInt16 port,
822                                              SilcSocketType type)
823 {
824   int i, count;
825
826   if (!ip && !hostname)
827     return 0;
828
829   for (i = 0, count = 0; i < server->config->param.connections_max; i++) {
830     if (server->sockets[i] && 
831         ((ip && !strcmp(server->sockets[i]->ip, ip)) ||
832          (hostname && !strcmp(server->sockets[i]->hostname, hostname))) &&
833         server->sockets[i]->port == port &&
834         server->sockets[i]->type == type)
835       count++;
836   }
837
838   return count;
839 }
840
841 /* Finds locally cached public key by the public key received in the SKE. 
842    If we have it locally cached then we trust it and will use it in the
843    authentication protocol.  Returns the locally cached public key or NULL
844    if we do not find the public key.  */
845
846 SilcPublicKey silc_server_find_public_key(SilcServer server, 
847                                           SilcHashTable local_public_keys,
848                                           SilcPublicKey remote_public_key)
849 {
850   SilcPublicKey cached_key;
851
852   SILC_LOG_DEBUG(("Find remote public key (%d keys in local cache)",
853                   silc_hash_table_count(local_public_keys)));
854
855   if (!silc_hash_table_find_ext(local_public_keys, remote_public_key,
856                                 (void **)&cached_key, NULL, 
857                                 silc_hash_public_key, NULL,
858                                 silc_hash_public_key_compare, NULL)) {
859     SILC_LOG_ERROR(("Public key not found"));
860     return NULL;
861   }
862
863   SILC_LOG_DEBUG(("Found public key"));
864
865   return cached_key;
866 }
867
868 /* This returns the first public key from the table of public keys.  This
869    is used only in cases where single public key exists in the table and
870    we want to get a pointer to it.  For public key tables that has multiple
871    keys in it the silc_server_find_public_key must be used. */
872
873 SilcPublicKey silc_server_get_public_key(SilcServer server,
874                                          SilcHashTable local_public_keys)
875 {
876   SilcPublicKey cached_key;
877   SilcHashTableList htl;
878
879   SILC_LOG_DEBUG(("Start"));
880
881   assert(silc_hash_table_count(local_public_keys) < 2);
882
883   silc_hash_table_list(local_public_keys, &htl);
884   if (!silc_hash_table_get(&htl, NULL, (void **)&cached_key))
885     return NULL;
886   silc_hash_table_list_reset(&htl);
887
888   return cached_key;
889 }
890
891 /* Check whether the connection `sock' is allowed to connect to us.  This
892    checks for example whether there is too much connections for this host,
893    and required version for the host etc. */
894
895 bool silc_server_connection_allowed(SilcServer server, 
896                                     SilcSocketConnection sock,
897                                     SilcSocketType type,
898                                     SilcServerConfigConnParams *global,
899                                     SilcServerConfigConnParams *params,
900                                     SilcSKE ske)
901 {
902   SilcUInt32 conn_number = (type == SILC_SOCKET_TYPE_CLIENT ?
903                             server->stat.my_clients :
904                             type == SILC_SOCKET_TYPE_SERVER ?
905                             server->stat.my_servers :
906                             server->stat.my_routers);
907   SilcUInt32 num_sockets, max_hosts, max_per_host;
908   SilcUInt32 r_protocol_version, l_protocol_version;
909   SilcUInt32 r_software_version, l_software_version;
910   char *r_vendor_version = NULL, *l_vendor_version;
911
912   /* Check version */
913
914   l_protocol_version = 
915     silc_version_to_num(params && params->version_protocol ? 
916                         params->version_protocol : 
917                         global->version_protocol);
918   l_software_version = 
919     silc_version_to_num(params && params->version_software ? 
920                         params->version_software : 
921                         global->version_software);
922   l_vendor_version = (params && params->version_software_vendor ? 
923                       params->version_software_vendor : 
924                       global->version_software_vendor);
925   
926   if (ske && silc_ske_parse_version(ske, &r_protocol_version, NULL,
927                                     &r_software_version, NULL,
928                                     &r_vendor_version)) {
929     sock->version = r_protocol_version;
930
931     /* Match protocol version */
932     if (l_protocol_version && r_protocol_version &&
933         r_protocol_version < l_protocol_version) {
934       SILC_LOG_INFO(("Connection %s (%s) is too old version",
935                      sock->hostname, sock->ip));
936       silc_server_disconnect_remote(server, sock, 
937                                     "Server closed connection: "
938                                     "You support too old protocol version");
939       return FALSE;
940     }
941
942     /* Math software version */
943     if (l_software_version && r_software_version &&
944         r_software_version < l_software_version) {
945       SILC_LOG_INFO(("Connection %s (%s) is too old version",
946                      sock->hostname, sock->ip));
947       silc_server_disconnect_remote(server, sock, 
948                                     "Server closed connection: "
949                                     "You support too old software version");
950       return FALSE;
951     }
952
953     /* Regex match vendor version */
954     if (l_vendor_version && r_vendor_version && 
955         !silc_string_match(l_vendor_version, r_vendor_version)) {
956       SILC_LOG_INFO(("Connection %s (%s) is unsupported version",
957                      sock->hostname, sock->ip));
958       silc_server_disconnect_remote(server, sock, 
959                                     "Server closed connection: "
960                                     "Your software is not supported");
961       return FALSE;
962     }
963   }
964   silc_free(r_vendor_version);
965
966   /* Check for maximum connections limit */
967
968   num_sockets = silc_server_num_sockets_by_ip(server, sock->ip, type);
969   max_hosts = (params ? params->connections_max : global->connections_max);
970   max_per_host = (params ? params->connections_max_per_host :
971                   global->connections_max_per_host);
972
973   if (max_hosts && conn_number >= max_hosts) {
974     SILC_LOG_INFO(("Server is full, closing %s (%s) connection",
975                    sock->hostname, sock->ip));
976     silc_server_disconnect_remote(server, sock, 
977                                   "Server closed connection: "
978                                   "Server is full, try again later");
979     return FALSE;
980   }
981
982   if (num_sockets >= max_per_host) {
983     SILC_LOG_INFO(("Too many connections from %s (%s), closing connection",
984                    sock->hostname, sock->ip));
985     silc_server_disconnect_remote(server, sock, 
986                                   "Server closed connection: "
987                                   "Too many connections from your host");
988     return FALSE;
989   }
990
991   return TRUE;
992 }
993
994 /* Checks that client has rights to add or remove channel modes. If any
995    of the checks fails FALSE is returned. */
996
997 bool silc_server_check_cmode_rights(SilcServer server,
998                                     SilcChannelEntry channel,
999                                     SilcChannelClientEntry client,
1000                                     SilcUInt32 mode)
1001 {
1002   bool is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1003   bool is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1004
1005   /* Check whether has rights to change anything */
1006   if (!is_op && !is_fo)
1007     return FALSE;
1008
1009   /* Check whether has rights to change everything */
1010   if (is_op && is_fo)
1011     return TRUE;
1012
1013   /* We know that client is channel operator, check that they are not
1014      changing anything that requires channel founder rights. Rest of the
1015      modes are available automatically for channel operator. */
1016
1017   if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1018     if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
1019       if (is_op && !is_fo)
1020         return FALSE;
1021   } else {
1022     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1023       if (is_op && !is_fo)
1024         return FALSE;
1025     }
1026   }
1027   
1028   if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1029     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
1030       if (is_op && !is_fo)
1031         return FALSE;
1032   } else {
1033     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1034       if (is_op && !is_fo)
1035         return FALSE;
1036     }
1037   }
1038
1039   if (mode & SILC_CHANNEL_MODE_CIPHER) {
1040     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
1041       if (is_op && !is_fo)
1042         return FALSE;
1043   } else {
1044     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1045       if (is_op && !is_fo)
1046         return FALSE;
1047     }
1048   }
1049   
1050   if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1051     if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
1052       if (is_op && !is_fo)
1053         return FALSE;
1054   } else {
1055     if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1056       if (is_op && !is_fo)
1057         return FALSE;
1058     }
1059   }
1060   
1061   if (mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1062     if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS))
1063       if (is_op && !is_fo)
1064         return FALSE;
1065   } else {
1066     if (channel->mode & SILC_CHANNEL_MODE_SILENCE_USERS) {
1067       if (is_op && !is_fo)
1068         return FALSE;
1069     }
1070   }
1071   
1072   if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1073     if (!(channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS))
1074       if (is_op && !is_fo)
1075         return FALSE;
1076   } else {
1077     if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS) {
1078       if (is_op && !is_fo)
1079         return FALSE;
1080     }
1081   }
1082   
1083   return TRUE;
1084 }
1085
1086 /* Check that the client has rights to change its user mode.  Returns
1087    FALSE if setting some mode is not allowed. */
1088
1089 bool silc_server_check_umode_rights(SilcServer server,
1090                                     SilcClientEntry client,
1091                                     SilcUInt32 mode)
1092 {
1093   bool server_op = FALSE, router_op = FALSE;
1094
1095   if (mode & SILC_UMODE_SERVER_OPERATOR) {
1096     /* Cannot set server operator mode (must use OPER command) */
1097     if (!(client->mode & SILC_UMODE_SERVER_OPERATOR))
1098       return FALSE;
1099   } else {
1100     /* Remove the server operator rights */
1101     if (client->mode & SILC_UMODE_SERVER_OPERATOR)
1102       server_op = TRUE;
1103   }
1104
1105   if (mode & SILC_UMODE_ROUTER_OPERATOR) {
1106     /* Cannot set router operator mode (must use SILCOPER command) */
1107     if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR))
1108       return FALSE;
1109   } else {
1110     /* Remove the router operator rights */
1111     if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
1112       router_op = TRUE;
1113   }
1114
1115   if (server_op)
1116     SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR);
1117   if (router_op)
1118     SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR);
1119
1120   return TRUE;
1121 }
1122
1123 /* This function is used to send the notify packets and motd to the
1124    incoming client connection. */
1125
1126 void silc_server_send_connect_notifys(SilcServer server,
1127                                       SilcSocketConnection sock,
1128                                       SilcClientEntry client)
1129 {
1130   SilcIDListData idata = (SilcIDListData)client;
1131
1132   /* Send some nice info to the client */
1133   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1134                           ("Welcome to the SILC Network %s",
1135                            client->username));
1136   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1137                           ("Your host is %s, running version %s",
1138                            server->server_name, server_version));
1139
1140   if (server->stat.clients && server->stat.servers + 1)
1141     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1142                             ("There are %d clients on %d servers in SILC "
1143                              "Network", server->stat.clients,
1144                              server->stat.servers + 1));
1145   if (server->stat.cell_clients && server->stat.cell_servers + 1)
1146     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1147                             ("There are %d clients on %d server in our cell",
1148                              server->stat.cell_clients,
1149                              server->stat.cell_servers + 1));
1150   if (server->server_type == SILC_ROUTER) {
1151     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1152                             ("I have %d clients, %d channels, %d servers and "
1153                              "%d routers",
1154                              server->stat.my_clients, 
1155                              server->stat.my_channels,
1156                              server->stat.my_servers,
1157                              server->stat.my_routers));
1158   } else {
1159     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1160                             ("I have %d clients and %d channels formed",
1161                              server->stat.my_clients,
1162                              server->stat.my_channels));
1163   }
1164
1165   if (server->stat.server_ops || server->stat.router_ops)
1166     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1167                             ("There are %d server operators and %d router "
1168                              "operators online",
1169                              server->stat.server_ops,
1170                              server->stat.router_ops));
1171   if (server->stat.my_router_ops + server->stat.my_server_ops)
1172     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1173                             ("I have %d operators online",
1174                              server->stat.my_router_ops +
1175                              server->stat.my_server_ops));
1176
1177   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1178                           ("Your connection is secured with %s cipher, "
1179                            "key length %d bits",
1180                            idata->send_key->cipher->name,
1181                            idata->send_key->cipher->key_len));
1182   SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
1183                           ("Your current nickname is %s",
1184                            client->nickname));
1185
1186   /* Send motd */
1187   silc_server_send_motd(server, sock);
1188 }
1189
1190 /* Kill the client indicated by `remote_client' sending KILLED notify
1191    to the client, to all channels client has joined and to primary
1192    router if needed.  The killed client is also removed from all channels. */
1193
1194 void silc_server_kill_client(SilcServer server,
1195                              SilcClientEntry remote_client,
1196                              const char *comment,
1197                              void *killer_id,
1198                              SilcIdType killer_id_type)
1199 {
1200   SilcBuffer killed, killer;
1201
1202   /* Send the KILL notify packets. First send it to the channel, then
1203      to our primary router and then directly to the client who is being
1204      killed right now. */
1205
1206   killed = silc_id_payload_encode(remote_client->id, SILC_ID_CLIENT);
1207   killer = silc_id_payload_encode(killer_id, killer_id_type);
1208
1209   /* Send KILLED notify to the channels. It is not sent to the client
1210      as it will be sent differently destined directly to the client and not
1211      to the channel. */
1212   silc_server_send_notify_on_channels(server, remote_client, 
1213                                       remote_client, SILC_NOTIFY_TYPE_KILLED,
1214                                       3, killed->data, killed->len,
1215                                       comment, comment ? strlen(comment) : 0,
1216                                       killer->data, killer->len);
1217
1218   /* Send KILLED notify to primary route */
1219   if (!server->standalone)
1220     silc_server_send_notify_killed(server, server->router->connection, TRUE,
1221                                    remote_client->id, comment, 
1222                                    killer_id, killer_id_type);
1223
1224   /* Send KILLED notify to the client directly */
1225   if (remote_client->connection || remote_client->router)
1226     silc_server_send_notify_killed(server, remote_client->connection ? 
1227                                    remote_client->connection : 
1228                                    remote_client->router->connection, FALSE,
1229                                    remote_client->id, comment, 
1230                                    killer_id, killer_id_type);
1231
1232   /* Remove the client from all channels. This generates new keys to the
1233      channels as well. */
1234   silc_server_remove_from_channels(server, NULL, remote_client, FALSE, 
1235                                    NULL, TRUE);
1236
1237   /* Remove the client entry, If it is locally connected then we will also
1238      disconnect the client here */
1239   if (remote_client->connection) {
1240     /* Remove locally conneted client */
1241     SilcSocketConnection sock = remote_client->connection;
1242     silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
1243     silc_server_close_connection(server, sock);
1244   } else {
1245     /* Update statistics */
1246     server->stat.clients--;
1247     server->stat.my_clients--;
1248     if (server->stat.cell_clients)
1249       server->stat.cell_clients--;
1250     SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
1251     SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
1252
1253     /* Remove remote client */
1254     if (!silc_idlist_del_client(server->global_list, remote_client))
1255       silc_idlist_del_client(server->local_list, remote_client);  
1256 }
1257
1258   silc_buffer_free(killer);
1259   silc_buffer_free(killed);
1260 }