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