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