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