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